Desligamento normal, opções persistentes e fechamento de soquete

O material a seguir é fornecido como esclarecimento para o assunto de desligar as conexões de soquete que fecham os soquetes. É importante distinguir a diferença entre desligar uma conexão de soquete e fechar um soquete.

Desligar uma conexão de soquete envolve uma troca de mensagens de protocolo entre os dois pontos de extremidade, posteriormente chamados de sequência de desligamento. Duas classes gerais de sequências de desligamento são definidas: normal e abortiva (também chamada de hard). Em uma sequência de desligamento normal, todos os dados que foram enfileirados, mas ainda não transmitidos, podem ser enviados antes do fechamento da conexão. Em um desligamento anulativo, todos os dados não solicitados são perdidos. A ocorrência de uma sequência de desligamento (normal ou anulativa) também pode ser usada para fornecer uma indicação FD_CLOSE aos aplicativos associados, significando que um desligamento está em andamento.

Fechar um soquete, por outro lado, faz com que o identificador do soquete seja desalocado para que o aplicativo não possa mais referenciar ou usar o soquete de qualquer maneira.

No Windows Sockets, a função de desligamento e a função WSASendDisconnect podem ser usadas para iniciar uma sequência de desligamento, enquanto a função closesocket é usada para desalocar identificadores de soquete e liberar todos os recursos associados. Alguma quantidade de confusão surge, no entanto, do fato de que a função closesocket implicitamente faz com que uma sequência de desligamento ocorra se ela ainda não tiver acontecido. Na verdade, tornou-se uma prática de programação bastante comum confiar nesse recurso e usar closesocket para iniciar a sequência de desligamento e desalocar o identificador do soquete.

Para facilitar esse uso, a interface de soquetes fornece controles por meio do mecanismo de opção de soquete que permite que o programador indique se a sequência de desligamento implícito deve ser normal ou abortiva e também se a função closesocket deve permanecer (isso não está concluído imediatamente) para permitir que uma sequência de desligamento normal seja concluída. Essas distinções importantes e as ramificações do uso de closesocket dessa maneira ainda não são amplamente compreendidas.

Ao estabelecer valores apropriados para as opções de soquete SO_LINGER e SO_DONTLINGER, os seguintes tipos de comportamento podem ser obtidos com a função closesocket :

  • Sequência de desligamento abortivo, retorno imediato de closesocket.
  • Desligamento normal, atrasando o retorno até que a sequência de desligamento seja concluída ou um intervalo de tempo especificado decorrido. Se o intervalo de tempo expirar antes da conclusão da sequência de desligamento normal, ocorrerá uma sequência de desligamento abortivo e fechará oocket .
  • Desligamento normal, retorno imediato, permitindo que a sequência de desligamento seja concluída em segundo plano. Embora esse seja o comportamento padrão, o aplicativo não tem como saber quando (ou se) a sequência de desligamento normal realmente é concluída.

O uso das opções de soquete SO_LINGER e SO_DONTLINGER e da estrutura persistente associada é discutido mais detalhadamente nas seções de referência sobre SOL_SOCKET Opções de Soquete e a estrutura persistente .

Uma técnica que pode ser usada para minimizar a chance de problemas ocorrerem durante a remoção da conexão é evitar depender de um desligamento implícito iniciado por closesocket. Em vez disso, use uma das duas funções de desligamento explícitas, desligamento ou WSASendDisconnect. Isso, por sua vez, faz com que uma indicação de FD_CLOSE seja recebida pelo aplicativo par indicando que todos os dados pendentes foram recebidos. Para ilustrar isso, a tabela a seguir mostra as funções que seriam invocadas pelos componentes cliente e servidor de um aplicativo, em que o cliente é responsável por iniciar um desligamento normal.

Lado do cliente Lado do Servidor
(1) Invoca desligamentos, SD_SEND) para sinalizar o fim da sessão e esse cliente não tem mais dados para enviar.
(2) Recebe FD_CLOSE, indicando o desligamento normal em andamento e que todos os dados foram recebidos.
(3) Envia todos os dados de resposta restantes.
(somente significância de tempo local) Obtém FD_READ e chama recv para obter todos os dados de resposta enviados pelo servidor . (4) Invoca desligamentos, SD_SEND) para indicar que o servidor não tem mais dados a serem enviados.
(5) Recebe FD_CLOSE indicação. (somente significância de tempo local) Invoca closesocket .
(6) Invoca closesocket.