c# - receive - socket vb net
Cómo saber cuándo se ha desconectado un zócalo (5)
En el lado del cliente, necesito saber cuándo / si mi conexión de socket se ha roto. Sin embargo, la propiedad Socket.Connected siempre devuelve verdadero, incluso después de que se haya desconectado el lado del servidor y he intentado enviar datos a través de él. ¿Alguien puede ayudarme a descubrir qué está pasando aquí? Necesito saber cuándo se ha desconectado un enchufe.
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
¿El método clientSocket.Send () espera a que el paquete sea ack / nack''d?
Si no, su código está volando a la siguiente línea mientras que el socket aún está tratando de descubrir qué está pasando.
¿Quizás la solución es enviar algunos datos ficticios a través de ella y verificar si se agota el tiempo?
Después de hacer algunas pruebas, parece que la documentación de Socket.Connected es incorrecta, o al menos engañosa. clientSocket.Connected
solo se convertirá en falso después de clientSocket.close()
. Creo que esto es un retroceso a la API original de sockets de C Berkeley y su terminología. Un socket está vinculado cuando tiene una dirección local asociada, y un socket está conectado cuando tiene una dirección remota asociada. Aunque el lado remoto ha cerrado la conexión, el socket local todavía tiene la asociación y, por lo tanto, todavía está "conectado".
Sin embargo, aquí hay un método que funciona:
!(socket.Poll(0, SelectMode.SelectRead) && socket.Available == 0)
Se basa en el hecho de que una conexión cerrada se marcará como legible aunque no haya datos disponibles.
Si desea detectar abruptamente la desconexión de condiciones como cables de red rotos o computadoras, la situación es un poco más compleja. En esas condiciones, su computadora nunca recibe un paquete que indique que el socket se ha cerrado. Necesita detectar que el lado remoto se ha desvanecido enviando paquetes y notando que no hay respuesta. Puede hacerlo a nivel de aplicación como parte de su protocolo, o puede usar la opción TCP KeepAlive. Usar TCP Keep Alive desde .NET no es particularmente fácil; probablemente sea mejor que construyas un mecanismo de mantener vivo tu protocolo (alternativamente, podrías hacer una pregunta por separado para "¿Cómo habilito TCP Keep Alive en .NET y establezco el intervalo de mantener activo?").
Recomiendo eliminar el lenguaje de nivel superior y explorar qué sucede en el IO de nivel inferior.
Lo más bajo que he explorado fue mientras escribía isectd (find en sourceforge). Al usar la llamada al sistema select (), un descriptor para un socket cerrado se convierte en listo para lectura, y cuando se intente, se puede confirmar la conexión () del estado desconectado del socket.
Como solución, recomiendo no escribir su propio socket IO y usar el middleware de otra persona. Hay muchos buenos candidatos por ahí. No se olvide de considerar los servicios de colas simples también.
PD. Hubiera proporcionado direcciones URL a todo lo anterior, pero mi reputación (1) no lo permite.
Simplemente escribe en tu socket como siempre. Sabrá cuándo está desconectado por la Excepción que dice que sus datos no pudieron ser entregados.
Si no tienes nada que escribir ... ¿a quién le importa si está desconectado? Puede estar desconectado ahora, pero vuelve antes de que lo necesites, ¿por qué molestarse en derribarlo y luego volver a conectarlo hasta que se repare el enlace ... especialmente cuando no tenías nada que decir de todos modos?
Si te molesta, implementa un mantener vivo en tu protocolo. Entonces tendrás algo que decir cada 30 segundos más o menos.