socket receive example ejemplo data and c# sockets tcpclient networkstream

c# - receive - ¿Cómo verificar si TcpClient Connection está cerrado?



tcpclient c# ejemplo (7)

Estoy jugando con el TcpClient y estoy tratando de averiguar cómo hacer que la propiedad Connected diga falso cuando se corta una conexión.

Intenté hacer

NetworkStream ns = client.GetStream(); ns.Write(new byte[1], 0, 0);

Pero todavía no me mostrará si el TcpClient está desconectado. ¿Cómo harías con un TcpClient?


Creé esta función y trabajé para que compruebe si el cliente todavía está conectado con el servidor.

/// <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; }


En mi caso, estaba enviando un comando a un servidor (ejecutándose en una máquina virtual en la misma computadora) y esperando la respuesta. Sin embargo, si el servidor se detuvo inesperadamente mientras esperaba, no recibí ninguna notificación. Intenté las posibilidades propuestas por los otros carteles, pero tampoco funcionó (siempre decía que el servidor todavía estaba conectado). Para mí, lo único que funciona es escribir 0 bytes en la transmisión:

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); }


La respuesta de @uriel funciona muy bien para mí, pero necesitaba codificarla en C ++ / CLI, que no era del todo trivial. Aquí está el código C ++ / CLI (aproximadamente equivalente), con algunas comprobaciones de robustez agregadas para una buena medida.

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; }

Espero que esto ayude a alguien.


La solución de Peter Wone y uriel es muy buena. Pero también debe verificar el punto extremo remoto, ya que puede tener múltiples conexiones abiertas a su punto final local.

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; }


No recomendaría que intentes escribir solo para probar el socket. Y tampoco retransmita en la propiedad Connected de .NET.

Si desea saber si el punto final remoto todavía está activo, puede usar 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();

Ver también:
TcpConnectionInformation en MSDN
IPGlobalProperties en MSDN
Descripción de los estados de TcpState
Netstat en Wikipedia

Y aquí está como un método de extensión en 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; }


Por lo que sé / recuerdo, no hay forma de probar si un enchufe está conectado, además de leer o escribir en él.

No he usado el TcpClient en absoluto, pero la clase Socket devolverá 0 desde una llamada a Read si el extremo remoto se ha apagado correctamente. Si el extremo remoto no se cierra con gracia [creo] se obtiene una excepción de tiempo de espera, no puedo recordar el tipo lo siento.

El uso de un código como '' if(socket.Connected) { socket.Write(...) } crea una condición de carrera. Es mejor simplemente llamar al socket. Escribir y manejar las excepciones y / o desconexiones.


Prueba esto, funciona para mí

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(); } }

utilicé el temporizador porque, quería verificar el estado de la conexión a intervalos regulares y no en un LOOP con el código de escucha [sentí que estaba ralentizando el proceso de envío de recepción]