如何检查TcpClient连接是否closures?
我正在玩TcpClient,我试图弄清楚如何使连接属性在断开连接时显示为false。
我试过了
NetworkStream ns = client.GetStream(); ns.Write(new byte[1], 0, 0);
但是如果TcpClient断开,它仍然不会显示出来。 你将如何去使用TcpClient?
我不会推荐你尝试写testing套接字。 而且不要在.NET的Connected属性上传递。
如果您想知道远程端点是否仍处于活动状态,则可以使用TcpConnectionInformation:
TcpClient client = new TcpClient(host, port); IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties(); TcpConnectionInformation[] tcpConnections = ipProperties.GetActiveTcpConnections().Where(x => x.LocalEndPoint.Equals(client.Client.LocalEndPoint) && x.RemoteEndPoint.Equals(client.Client.RemoteEndPoint)).ToArray(); if (tcpConnections != null && tcpConnections.Length > 0) { TcpState stateOfConnection = tcpConnections.First().State; if (stateOfConnection == TcpState.Established) { // Connection is OK } else { // No active tcp Connection to hostName:port } } client.Close();
也可以看看:
MSDN上的TcpConnectionInformation
IPGlobalProperties在MSDN上
TcpState状态的描述
Netstat在维基百科
在这里它是作为TcpClient的扩展方法。
public static TcpState GetState(this TcpClient tcpClient) { var foo = IPGlobalProperties.GetIPGlobalProperties() .GetActiveTcpConnections() .SingleOrDefault(x => x.LocalEndPoint.Equals(tcpClient.Client.LocalEndPoint)); return foo != null ? foo.State : TcpState.Unknown; }
据我所知/记住,没有办法testing一个套接字是否连接,而不是读取或写入它。
我根本没有使用过TcpClient,但是如果远端已经正常closures,Socket类将从调用返回0。 如果远端没有正常关机[我认为]你得到一个超时exception,不记得types抱歉。
使用像' if(socket.Connected) { socket.Write(...) }
创build竞争条件。 只需调用socket.Write并处理exception和/或断开连接就可以了。
@ uriel的答案非常适合我,但是我需要用C ++ / CLI编写代码,这并不是完全无关紧要的。 这里是(大致相当的)C ++ / CLI代码,join了一些健壮性检查。
using namespace System::Net::Sockets; using namespace System::Net::NetworkInformation; TcpState GetTcpConnectionState(TcpClient ^ tcpClient) { TcpState tcpState = TcpState::Unknown; if (tcpClient != nullptr) { // Get all active TCP connections IPGlobalProperties ^ ipProperties = IPGlobalProperties::GetIPGlobalProperties(); array<TcpConnectionInformation^> ^ tcpConnections = ipProperties->GetActiveTcpConnections(); if ((tcpConnections != nullptr) && (tcpConnections->Length > 0)) { // Get the end points of the TCP connection in question EndPoint ^ localEndPoint = tcpClient->Client->LocalEndPoint; EndPoint ^ remoteEndPoint = tcpClient->Client->RemoteEndPoint; // Run through all active TCP connections to locate TCP connection in question for (int i = 0; i < tcpConnections->Length; i++) { if ((tcpConnections[i]->LocalEndPoint->Equals(localEndPoint)) && (tcpConnections[i]->RemoteEndPoint->Equals(remoteEndPoint))) { // Found active TCP connection in question tcpState = tcpConnections[i]->State; break; } } } } return tcpState; } bool TcpConnected(TcpClient ^ tcpClient) { bool bTcpConnected = false; if (tcpClient != nullptr) { if (GetTcpConnectionState(tcpClient) == TcpState::Established) { bTcpConnected = true; } } return bTcpConnected; }
希望这会帮助别人。
我已经创build了这个function,并为我工作,以检查客户端是否仍然连接到服务器。
/// <summary> /// THIS FUNCTION WILL CHECK IF CLIENT IS STILL CONNECTED WITH SERVER. /// </summary> /// <returns>FALSE IF NOT CONNECTED ELSE TRUE</returns> public bool isClientConnected() { IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties(); TcpConnectionInformation[] tcpConnections = ipProperties.GetActiveTcpConnections(); foreach (TcpConnectionInformation c in tcpConnections) { TcpState stateOfConnection = c.State; if (c.LocalEndPoint.Equals(ClientSocket.Client.LocalEndPoint) && c.RemoteEndPoint.Equals(ClientSocket.Client.RemoteEndPoint)) { if (stateOfConnection == TcpState.Established) { return true; } else { return false; } } } return false; }
Peter Wone和uriel的解决scheme非常好。 但是您也需要检查远程端点,因为您可以有多个打开连接到您的本地端点。
public static TcpState GetState(this TcpClient tcpClient) { var foo = IPGlobalProperties.GetIPGlobalProperties() .GetActiveTcpConnections() .SingleOrDefault(x => x.LocalEndPoint.Equals(tcpClient.Client.LocalEndPoint) && x.RemoteEndPoint.Equals(tcpClient.Client.RemoteEndPoint) ); return foo != null ? foo.State : TcpState.Unknown; }
在我的情况下,我发送一些命令到服务器(在同一台计算机上的虚拟机上运行)并等待响应。 但是,如果服务器在等待时意外停止,我没有收到任何通知。 我尝试了其他海报提出的可能性,但都没有工作(它总是说服务器仍然连接)。 对我来说,唯一的工作是写入0字节的stream:
var client = new TcpClient(); //... open the client var stream = client.GetStream(); //... send something to the client byte[] empty = { 0 }; //wait for response from server while (client.Available == 0) { //throws a SocketException if the connection is closed by the server stream.Write(empty, 0, 0); Thread.Sleep(10); }
试试这个,对我有用
private void timer1_Tick(object sender, EventArgs e) { if (client.Client.Poll(0, SelectMode.SelectRead)) { if (!client.Connected) sConnected = false; else { byte[] b = new byte[1]; try { if (client.Client.Receive(b, SocketFlags.Peek) == 0) { // Client disconnected sConnected = false; } } catch { sConnected = false; } } } if (!sConnected) { //--Basically what you want to do afterwards timer1.Stop(); client.Close(); ReConnect(); } }
我用定时器,因为,我想要定期检查连接状态,而不是在与听力代码的LOOP [我觉得这是减缓发送接收过程]