如何检测C中的套接字断开连接#

如何检测C中的套接字断开连接#

问题描述:

我正在处理一个客户端/服务器关系,这意味着无限量的时间来回推送数据。如何检测C中的套接字断开连接#

我试图克服的问题是在客户端,是我无法设法找到一种方法来检测断开连接。

我从其他人的解决方案中取得了一些通行证,从捕获IO异常到轮询所有三个SelectMode上的套接字。我也尝试过使用轮询的组合,并在套接字的'可用'字段中进行检查。

// Something like this 
Boolean IsConnected() 
{ 
    try 
    { 
     bool part1 = this.Connection.Client.Poll(1000, SelectMode.SelectRead); 
     bool part2 = (this.Connection.Client.Available == 0); 

     if (part1 & part2) 
     { 
      // Never Occurs 
      //connection is closed 
      return false; 
     } 
     return true; 
    } 
    catch(IOException e) 
    { 
     // Never Occurs Either 
    } 
} 

在服务器端,写一个“空”字符的尝试(\ 0)到客户端强制IO异常和服务器可以检测该客户端已经断开(相当容易演出)。

在客户端,同样的操作不会产生异常。

// Something like this 
Boolean IsConnected() 
{ 
    try 
    { 

     this.WriteHandle.WriteLine("\0"); 
     this.WriteHandle.Flush(); 
     return true; 
    } 
    catch(IOException e) 
    { 
     // Never occurs 
     this.OnClosed("Yo socket sux"); 
     return false; 
    } 
} 

,我相信我在通过调查检测断开有一个问题,就是我可以很容易遇到一个错误上SelectRead,如果我的服务器还没有,因为写东西回客户端最后一次检查...不知道该怎么做,我已经追逐了每一个选项,使我能够找到这个检测,并且对我来说什么都没有100%,最终我的目标是检测服务器(或连接)失败,通知客户,等待重新连接等。所以我相信你可以想象这是一个不可或缺的部分。

欣赏任何人的建议。 提前致谢。

编辑:任何查看此问题的人都应该注意下面的答案以及我的最终评论。我详细阐述了我如何克服这个问题,但还没有制作'Q &'风格的帖子。

+0

只需捕获IOExceptions并使用读取超时。你不需要所有这些其他的malarkey。 – EJP 2012-08-06 23:23:09

+0

我已经尝试过(因为你没有真正阅读我的帖子...),它的命中或错过。读操作超时后会导致IO,这会强制断开连接......但是如果我只是没有收到数据......? – DigitalJedi805 2012-08-07 01:37:59

+0

我阅读了你的文章。它不是'碰撞和错过',它受到本地和远程异步数据缓冲的影响。在第一次写入失败的连接时,您将不会收到异常,因为它尚未被检测到:在TCP重新尝试超时后,您将在后续写入时获取它。 – EJP 2012-08-07 04:34:11

一个选项是使用TCP保持活动数据包。您打电话给Socket.IOControl()。只有恼人的一点是,它需要一个字节数组作为输入,所以你必须将数据转换为字节数组通过在这里的使用10000ms一个例子保持活动与1000毫秒重试:

Socket socket; //Make a good socket before calling the rest of the code. 
int size = sizeof(UInt32); 
UInt32 on = 1; 
UInt32 keepAliveInterval = 10000; //Send a packet once every 10 seconds. 
UInt32 retryInterval = 1000; //If no response, resend every second. 
byte[] inArray = new byte[size * 3]; 
Array.Copy(BitConverter.GetBytes(on), 0, inArray, 0, size); 
Array.Copy(BitConverter.GetBytes(keepAliveInterval), 0, inArray, size, size); 
Array.Copy(BitConverter.GetBytes(retryInterval), 0, inArray, size * 2, size); 
socket.IOControl(IOControlCode.KeepAliveValues, inArray, null); 

保持只有当您没有发送其他数据时才会发送活动数据包,因此每次发送数据时,10000ms定时器都将被复位。

+0

太棒了,谢谢乔尔,我一打开我的开发系统就一定会给我一个旋转。 – DigitalJedi805 2012-08-07 01:38:41

+0

嘿乔尔,所以我想我在这里得到的主意,但请纠正我,如果我是错的; IOControl方法在套接字上定时传递'KeepAlive'数据包。我(几乎一字不差)将上面的代码添加到了我的SocketServer.Client和SocketClient构造函数中。我把计时器减少到一秒钟(因为这是我双方'读'的超时?),但我的StreamReader.ReadLine(只是意识到我输入这个,这应该是我的策略)从来没有捕获任何数据...我必须说我不确定我们为什么要把我们要放入阵列的东西放在一起;我可以线路终止它吗? – DigitalJedi805 2012-08-07 16:10:02

+0

其实只是尝试用StreamReader.Read调用运行相同的东西,并且从来没有在任何方向上得到任何东西。可能是因为我不完全理解这个概念。 – DigitalJedi805 2012-08-07 16:14:25