在客户端,我需要知道我的套接字连接何时/是否已被破坏。但是,即使服务器端已断开连接并且我已尝试通过它发送数据,Socket.Connected属性也始终返回true。任何人都可以帮我弄清楚这里发生了什么。我需要知道套接字何时断开连接。
Socket serverSocket = null;
TcpListener listener = new TcpListener(1530);
listener.Start();
listener.BeginAcceptSocket(new AsyncCallback(delegate(IAsyncResult result)
{
Debug.WriteLine("ACCEPTING SOCKET CONNECTION");
TcpListener currentListener = (TcpListener)result.AsyncState;
serverSocket = currentListener.EndAcceptSocket(result);
}), listener);
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be FALSE, and it is
clientSocket.Connect("localhost", 1530);
Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be TRUE, and it is
Thread.Sleep(1000);
serverSocket.Close();//closing the server socket here
Thread.Sleep(1000);
clientSocket.Send(new byte[0]);//sending data should cause the socket to update its Connected property.
Debug.WriteLine("client socket connected: " + clientSocket.Connected);//should be FALSE, but its always TRUE
答案 0 :(得分:10)
在进行一些测试之后,似乎Socket.Connected的文档是错误的,或者至少是误导性的。 clientSocket.Connected
只会在调用clientSocket.close()
后变为false。我认为这是原始C Berkeley套接字API及其术语的回归。当套接字具有与之关联的本地地址时绑定套接字,并且当套接字具有与之关联的远程地址时,将连接套接字。即使远程端已关闭连接,本地套接字仍然具有关联,因此它仍然“连接”。
但是,这是一个 工作的方法:
!(socket.Poll(0, SelectMode.SelectRead) && socket.Available == 0)
它依赖于这样一个事实:即使没有数据可用,封闭连接也会被标记为可读。
如果要检测网络电缆断开或计算机突然关闭等情况,情况会更复杂一些。在这些情况下,您的计算机永远不会收到指示套接字已关闭的数据包。它需要通过发送数据包并注意到没有响应返回来检测远程端已经消失。您可以在应用程序级别执行此操作作为协议的一部分,也可以使用TCP KeepAlive选项。使用.NET Keep Alive from .NET并不是特别容易;你可能最好在你的协议中构建一个保持活动机制(或者,你可以问一个单独的问题“如何在.NET中启用TCP保持活动并设置保持活动间隔?”)。
答案 1 :(得分:4)
正常写入您的套接字。您将知道什么时候它被异常断开,表示您的数据无法传递。
如果你没有任何东西要写......那么谁在乎它是否已断开连接?它现在可能已断开连接,但在您需要它之前回来 - 为什么要将它拆掉,然后循环重新连接直到链接被修复...特别是当您没有任何要说的内容时?
如果它困扰你,请在你的协议中实现keep alive。那么你每隔30秒左右就会说些什么。
答案 2 :(得分:3)
也许解决方案是通过它发送一些虚拟数据并检查它是否超时?
答案 3 :(得分:2)
我建议剥离更高级别的语言,并探索在较低级别的IO中发生的事情。
我探索的最低价是写作isectd(在sourceforge上找到)。使用select()系统调用,闭合套接字的描述符变为就绪,当isectd尝试recv()时,可以确认套接字的断开状态。
作为解决方案,我建议不要编写自己的套接字IO并使用其他人的中间件。那里有很多优秀的候选人。不要忘记考虑简单的排队服务。
PS。我会提供以上所有的URL,但我的声誉(1)不允许。
答案 4 :(得分:0)
clientSocket.Send()方法是否等待数据包为ack / nack'd?
如果没有你的代码飞到下一行,而socket还在试图弄清楚发生了什么。