socket.shutdown vs socket.close
-
03-07-2019 - |
Pergunta
Recentemente, vi um pouco de código que olhou como este (com meia sendo um objeto de soquete é claro):
sock.shutdown(socket.SHUT_RDWR)
sock.close()
O que é exatamente o propósito de chamar shutdown na tomada e, em seguida, fechá-lo? Se ele faz a diferença, esta tomada está sendo usado para não-bloqueio IO.
Solução
Aqui está um explicação :
Uma vez que um socket não é mais necessária, o programa de chamada pode descartar a Tomada pela aplicação de uma sub-rotina perto para o descritor de socket. Se um soquete entrega fiável tem dados associada a ele quando uma estreita leva lugar, o sistema continua a tentar transferência de dados. No entanto, se os dados forem ainda não entregues, as devoluções do sistema os dados. Caso o pedido programa não tem nenhum uso para qualquer pendente dados, ele pode usar o desligamento sub-rotina sobre a tomada prévia fechá-lo.
Outras dicas
Chamando close
e shutdown
ter dois efeitos diferentes sobre o soquete subjacente.
A primeira coisa a salientar é que o soquete é um recurso no sistema operacional subjacente e vários processos podem ter uma alça para o mesmo soquete subjacente.
Quando você chama close
que diminui o número de identificador por um e se a contagem de identificador atingiu zero, então o soquete e conexão associados tramita perto normal (envio efetivamente um FIN / EOF para o peer) eo soquete é desalocada .
A única coisa a prestar atenção aqui é que se a contagem de identificador não chegar a zero porque outro processo ainda tem um identificador para o soquete em seguida, a conexão não está fechada e o socket não é desalocada.
Por outro lado chamando shutdown
para a leitura e escrita fecha a conexão subjacente e envia um FIN / EOF para o peer independentemente de quantos processos têm identificadores para o socket. No entanto, ele não desalocar o soquete e você ainda precisa chamar perto depois.
Explicação de desligamento e perto: desligamento (MSDN)
Shutdown (no seu caso) indica para a outra extremidade da conexão não há mais intenção de ler ou escrever para o socket. liberta em seguida, feche até qualquer memória associada com o soquete.
Omitting desligamento pode fazer com que o casquilho a ficar na pilha SOs até que a ligação tenha sido fechado normalmente.
IMO os nomes 'desligamento' e 'fechar' são enganosas, 'close' e 'destruir' seria enfatizar suas diferenças.
é mencionado mesmo no COMO FAZER Programação Socket ( PY2 / < a href = "http://docs.python.org/3/howto/sockets.html#disconnecting" rel = "noreferrer"> PY3 )
Desligar
Estritamente falando, você deveria usar
shutdown
em um soquete antes declose
-lo. Oshutdown
é um aviso à tomada na outra extremidade. Dependendo do argumento que você passá-lo, pode significar “ Eu não estou indo para enviar mais, mas eu ainda vou ouvir ”, ou “ Eu não estou escutando, boa viagem! ”. A maioria das bibliotecas de soquete, no entanto, estão tão acostumados a programadores deixar de usar este pedaço de etiqueta que normalmente umclose
é o mesmo queshutdown(); close()
. Assim, na maioria das situações, não é necessário um desligamento explícito....
Não é este código acima errado?
A triz diretamente após a chamada de desligamento pode fazer o kernel descartar todos os buffers de saída de qualquer maneira.
De acordo com http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable é preciso esperar entre o desligamento ea estreita até a volta de leitura 0.
existem alguns sabores de desligamento: http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.shutdown.aspx . * Nix é semelhante.
Shutdown (1), as forças da tomada nenhuma para enviar mais dados
Isso é útil em
1- Esvaziando buffer
2- erro estranho detecção
3 guarda de segurança
Deixe-me explicar mais, quando você enviar um conjunto de dados de A para B, não é garantido para ser enviado para B, só é garantido para ser enviado para o buffer de um sistema operacional, que por sua vez envia para o B OS tampão
Assim, chamando shutdown (1) em A, você tampão flush de A e será gerado um erro Se a memória intermédia não está vazia ou seja: dados não tiver sido enviado para o ponto ainda
Howoever este é irrevesable, para que possa fazer isso depois que você completamente enviou todos os seus dados e você quer ter certeza de que é pelo menos no par OS tampão