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

我正在研究一种客户端/服务器关系,它意味着在不确定的时间内来回推送数据。

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

我已经在其他人的解决方案上进行了几次传递,从捕获IOexception到轮询所有三个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)会强制执行IOexception,服务器可以检测到客户端已断开连接(非常简单)。

在客户端,相同的操作不会产生exception。

 // 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&A”风格的post。

一种选择是使用TCP保持活动包。 你通过调用Socket.IOControl()打开它们。 只有恼人的一点是它需要一个字节数组作为输入,所以你必须将你的数据转换成一个字节数组来传入。这是一个使用10000ms保持活动并重试1000ms的例子:

 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计时器。