Cierre correcto, opciones de persistencia y cierre de socket
El siguiente material se proporciona como aclaración para el asunto de apagar las conexiones de socket que cierran los sockets. Es importante distinguir la diferencia entre apagar una conexión de socket y cerrar un socket.
Apagar una conexión de socket implica un intercambio de mensajes de protocolo entre los dos puntos de conexión, a partir de entonces denominado secuencia de apagado. Se definen dos clases generales de secuencias de apagado: correcto y anulativo (también denominado duro). En una secuencia de apagado correcta, los datos que se han puesto en cola, pero que aún no se pueden transmitir se pueden enviar antes de que se cierre la conexión. En un apagado anulativo, se pierden los datos no enviados. La aparición de una secuencia de apagado (correcta o anulativa) también se puede usar para proporcionar una indicación de FD_CLOSE a las aplicaciones asociadas que indican que un apagado está en curso.
Cerrar un socket, por otro lado, hace que el identificador de socket se desasigne para que la aplicación ya no pueda hacer referencia o usar el socket de ninguna manera.
En Windows Sockets, tanto la funciónde apagadocomo la función WSASendDisconnect se pueden usar para iniciar una secuencia de apagado, mientras que la función closesocket se usa para desasignar identificadores de socket y liberar los recursos asociados. Sin embargo, se produce cierta confusión debido al hecho de que el closesocket función provoca implícitamente que se produzca una secuencia de apagado si aún no se ha producido. De hecho, se ha convertido en una práctica de programación bastante común para confiar en esta característica y usar closesocket para iniciar la secuencia de apagado y desasignar el identificador de socket.
Para facilitar este uso, la interfaz de sockets proporciona controles mediante el mecanismo de opción de socket que permite al programador indicar si la secuencia de apagado implícita debe ser correcta o anulativa, y también si la función de cierre de closesocket debe permanecer (que no se completa inmediatamente) para permitir que se complete una secuencia de apagado correcta. Estas importantes distinciones y las ramificaciones de usar closesocket de esta manera todavía no se entienden ampliamente.
Al establecer los valores adecuados para las opciones de socket SO_LINGER y SO_DONTLINGER, se pueden obtener los siguientes tipos de comportamiento con la funciónclosesocket de:
- Secuencia de apagado abortiva, retorno inmediato de closesocket.
- Apagado correcto, retrasando la devolución hasta que se completa la secuencia de apagado o un intervalo de tiempo especificado transcurre. Si el intervalo de tiempo expira antes de que se complete la secuencia de cierre correcta, se produce una secuencia de apagado anulativo y closesocket devuelve.
- Apagado correcto, devolución inmediata, lo que permite que la secuencia de apagado se complete en segundo plano. Aunque este es el comportamiento predeterminado, la aplicación no tiene forma de saber cuándo (o si) la secuencia de apagado correcta se completa realmente.
El uso de las opciones de socket de SO_LINGER y SO_DONTLINGER y la estructura dedepersistente asociada se describe con más detalle en las secciones de referencia sobreopciones de socket deSOL_SOCKET y la estructura de de persistente.
Una técnica que se puede usar para minimizar la posibilidad de que se produzcan problemas durante la desmontaje de la conexión es evitar depender de un apagado implícito iniciado por closesocket. En su lugar, use una de las dos funciones de apagado explícitas, apagado o WSASendDisconnect. Esto, a su vez, hace que la aplicación del mismo nivel reciba una indicación FD_CLOSE que indica que se han recibido todos los datos pendientes. Para ilustrar esto, en la tabla siguiente se muestran las funciones que invocarían los componentes de cliente y servidor de una aplicación, donde el cliente es responsable de iniciar un apagado correcto.
Lado cliente | Lado servidor |
---|---|
(1) Invoca apagado(s, SD_SEND) para indicar el final de la sesión y ese cliente no tiene más datos para enviar. | |
(2) Recibe FD_CLOSE, lo que indica el cierre correcto en curso y que se han recibido todos los datos. | |
(3) Envía los datos de respuesta restantes. | |
(solo significación de tiempo local) Obtiene FD_READ y llama a recv para obtener los datos de respuesta enviados por el servidor . | (4) Invoca de apagado (s, SD_SEND) para indicar que el servidor no tiene más datos que enviar. |
(5) Recibe FD_CLOSE indicación. | (solo significación de tiempo local) Invoca closesocket . |
(6) Invoca closesocket. |