2009-11-20 37 views
8

Tengo un objeto TcpClient que envía algunos datos al servidor, utilizando su NetworkStream.Write subyacente(). para el mismo, que tiene:Cuál es la forma correcta de cerrar una conexión TCP

TcpClient server = new TcpClient(serverName, 50001); 

/* ... */ 

NetworkStream stream = server.GetStream(); 

Ahora, cuando se pulsa un botón, la conexión debe cerrar. ¿Cuál es la forma correcta de cerrar la conexión? Los documentos de MSDN dicen que cerrar el TcpClient (con .Close()) de hecho no cierra el socket, solo los recursos de TcpClient (esa es al menos la forma en que entendí los documentos).

Entonces, ¿el siguiente código sería correcto al cerrar la conexión?

stream.Close(); 
server.Close(); 

¿Es esto lo suficiente, o debería primer cheque (de alguna manera) si la corriente (o servidor) se pueden cerrar (en caso de que la conexión está entreabierta o algo así) ...

Aún más , NetworkStream.Close() MSDN docs indica que libera recursos (incluso sockets), por lo que tal vez sea suficiente cerrar el flujo, teniendo en cuenta que evito usar el TcpClient después de ese punto.

¿Cuál es el enfoque correcto?

Respuesta

6

Como the docs dicen:

llamada a este método con el tiempo como resultado el cierre del zócalo asociado y también cerrará la NetworkStream asociado que se utiliza para enviar y recibir datos si se ha creado.

So server.Close(); será suficiente.

Cerrar el NetworkStream primero nunca va a doler.

Por cierto, si le toca estar utilizando el TcpClient sólo en un método, se envuelve en un comunicado using() modo que usted puede estar seguro Dispose() (equivalente a Close()) se llama en él, incluso si se producen excepciones, etc.

+1

supongo yo confiaba IntelliSense demasiado. La ventana emergente de TcpClient.Close() indica esto: "Elimina esta instancia de System.Net.Sockets.TcpClient sin cerrar la conexión subyacente". Cosa extraña. Gracias por la respuesta. –

+0

De hecho, eso es lo que dicen los documentos 3.0 (http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.close(VS.85).aspx) en la primera oración ... pero luego la tercera oración dice que * cierra * * Socket y NetworkStream. Los 3.5 documentos (que he vinculado anteriormente) son consistentes. Sospecho que la línea en los documentos 3.0 fue un error. – Joren

0

Tiene razón al cerrar la transmisión y luego el servidor. Esto debería dar como resultado que todos los sockets se cierren con éxito a lo largo del tiempo, como lo indica la documentación. Sin embargo, varios errores de rasguño en la cabeza me han enseñado la importante lección en el tiempo:

¡No olviden enjuagar!

stream.Flush(); 
stream.Close(); 
server.Close(); 

A menudo perderá algunos datos que pensó que podría haber enviado de otra manera. Esto también ayuda a garantizar que la transmisión esté vacía e inactiva cuando la cierre.

+9

De los documentos en NetworkStream: "El método Flush implementa el método Stream.Flush, sin embargo, como NetworkStream no está almacenado en el búfer, no tiene efecto en las transmisiones de red. Llamar al método Flush no arroja una excepción". Así que realmente no importa si enjuagas la corriente o no. – Joren

3

Asociaré una conexión TCP con un socket.

En general, el procedimiento es así: 1. Acabado el envío de datos Socket.Shutdown 2. Llamada con el parámetro SocketShutdown.Send 3. Bucle de recepción hasta que devuelva 0 o falla con una excepción 4.Llamar a Close()

He aquí una pequeña muestra de pseudo-código que es muy similar a C# :)

void CloseConnection(Socket socket) 
{ 
    socket.Send(/*last data of the connection*/); 
    socket.Shutdown(SocketShutdown.Send); 

    try 
    { 
     int read = 0; 
     while((read = socket.Receive(/*application data buffers*/)) > 0) 
     {} 
    } 
    catch 
    { 
     //ignore 
    } 
    socket.Close(); 
} 

Si se omiten los pasos primero y tercero - la pérdida de datos puede ocurrir.

Tomado de How to close TCP socket

+0

¡Justo lo que necesitaba, gracias! En mi caso, las otras respuestas no estaban funcionando. Pudo haber sido porque no estaba leyendo todos los datos disponibles del cliente en algunos casos (en algunos casos, devolvería un error antes de leer todos los datos, luego cerré la conexión). Con este método, inicia el apagado y luego lee cualquier otro dato de espera. – eselk

Cuestiones relacionadas