2010-03-31 5 views
16

Del 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.Cómo saber cuándo se ha desconectado un zócalo

 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

Consulte http://stackoverflow.com/questions/722240/instantly-detect-client-disconnection-from-server-socket para obtener más información. – EricLaw

Respuesta

0

hace el clientSocket.Send() Método de espera para el paquete a ser o bien ión/nack'd?

Si no es así, su código está volando a la siguiente línea mientras el socket todavía está tratando de descubrir qué está pasando.

+0

Puede poner un Thread.Sleep después del envío. No importa cuánto espere clientSocket.Connected se mantiene cierto. – BowserKingKoopa

9

Después de hacer algunas pruebas, parece que la documentación para Socket.Connected es incorrecta, o al menos engañosa. clientSocket.Connected solo se volverá falso después de llamar al 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í es un método que hace trabajo:

!(socket.Poll(0, SelectMode.SelectRead) && socket.Available == 0) 

Se basa en el hecho de que una conexión cerrada se marcará como legible a pesar de que no hay 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?").

+0

socket.Poll (0, SelectMode.SelectRead) siempre devuelve verdadero para mí incluso después de que se haya cerrado la conexión del lado del servidor. – BowserKingKoopa

+0

También los documentos msdn dicen que el método Poll no puede detectar ciertas condiciones "como un cable de red roto o que el host remoto se cerró de forma desagradable". Solo quiero saber si el socket del lado del servidor está allí o no, no me importa por qué no está allí. – BowserKingKoopa

+0

@BrowserKingKoopa: ¡Vaya! El código que originalmente publiqué probó que el socket está * desconectado *. Lo he arreglado Cuando el lado remoto se haya desconectado, Poll() devolverá verdadero pero socket. Está disponible 0. También agregué un párrafo sobre el manejo de cables de red rotos. –

3

¿Quizás la solución es enviar algunos datos ficticios a través de ella y verificar si se agota el tiempo de espera?

2

Recomiendo eliminar las cosas de lenguaje de nivel superior y explorar lo que 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.

PS. Hubiera proporcionado direcciones URL a todo lo anterior, pero mi reputación (1) no lo permite.

4

Simplemente escriba en su zócalo de forma normal. Sabrá cuándo está desconectado por la Excepción que dice que sus datos no pudieron ser entregados.

Si no tiene 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 arrancarlo 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.

+0

+1 si el servidor envió todos los datos y no se mantiene activo debe cerrar el socket y el cliente debe manejarlo adecuadamente. del lado del cliente si recibió todos los datos que quería, simplemente cierra la conexión también, el servidor lo manejará. debería simplemente detectar excepciones en la recepción/envío de s.Send para saber cuándo alguien está desconectado, Poll también arrojará una excepción en el socket desconectado – hoodoos

+0

Los enchufes funcionan en ambos sentidos, el problema principal es cuando usa push usando el socket pero el socket es d/c sin que usted lo sepa, por lo que no obtiene datos, ya que la lectura de la red proporciona datos pero no errores. –

Cuestiones relacionadas