Em C, entendi que, se fecharmos um soquete, isso significa que o soquete será destruído e poderá ser reutilizado posteriormente.
Que tal desligar? A descrição dizia que fecha metade de uma conexão duplex a esse soquete. Mas esse soquete será destruído como uma close
chamada de sistema?
c
sockets
networking
tshepang
fonte
fonte
Respostas:
Isso é explicado no guia de rede de Beej.
shutdown
é uma maneira flexível de bloquear a comunicação em uma ou ambas as direções. Quando o segundo parâmetro forSHUT_RDWR
, ele bloqueará o envio e o recebimento (comoclose
). No entanto,close
é a maneira de realmente destruir um soquete.Com
shutdown
, você ainda poderá receber dados pendentes que o parceiro já enviou (obrigado a Joey Adams por observar isso).fonte
shutdown
duas direções, mas não,close
é se você fez umaFILE
referência ao soquete usandofdopen
. Se vocêclose
usar o soquete, um arquivo recém-aberto poderá receber o mesmo fd, e o uso subsequente doFILE
mesmo lerá / gravará o local errado, o que pode ser muito ruim. Se você apenasshutdown
, o uso subseqüente doFILE
apenas dará erros até quefclose
seja chamado.shutdown
: sinalizar EOF para o par e ainda poder receber dados pendentes que o par enviou.Nenhuma das respostas existentes informa às pessoas como
shutdown
eclose
funciona no nível do protocolo TCP, portanto, vale a pena adicionar isso.Uma conexão TCP padrão é finalizada pela finalização em quatro direções:
No entanto, existe outra maneira "emergente" de fechar uma conexão TCP:
No meu teste com o Wireshark, com opções de soquete padrão,
shutdown
envia um pacote FIN para a outra extremidade, mas é tudo o que faz. Até que a outra parte envie o pacote FIN, você ainda poderá receber dados. Quando isso acontecer, vocêReceive
obterá um resultado de tamanho 0. Portanto, se você é o primeiro a desligar o "send", feche o soquete assim que terminar de receber os dados.Por outro lado, se você ligar
close
enquanto a conexão ainda estiver ativa (o outro lado ainda está ativo e você também pode ter dados não enviados no buffer do sistema), um pacote RST será enviado para o outro lado. Isso é bom para erros. Por exemplo, se você acha que a outra parte forneceu dados incorretos ou se recusou a fornecer dados (ataque do DOS?), Você pode fechar o soquete imediatamente.Minha opinião sobre as regras seria:
shutdown
antes,close
quando possívelImplementações ideais para SHUT_RD e SHUT_WR
O seguinte não foi testado, confie em seu próprio risco. No entanto, acredito que essa é uma maneira razoável e prática de fazer as coisas.
Se a pilha TCP receber um desligamento apenas com SHUT_RD, marcará essa conexão como não há mais dados esperados. Quaisquer
read
solicitações pendentes e subseqüentes (independentemente do segmento em que estão) serão retornadas com resultado de tamanho zero. No entanto, a conexão ainda está ativa e utilizável - você ainda pode receber dados OOB, por exemplo. Além disso, o sistema operacional eliminará todos os dados que receber para esta conexão. Mas isso é tudo, nenhum pacote será enviado para o outro lado.Se a pilha TCP receber um desligamento apenas com SHUT_WR, marcará essa conexão como não mais dados podem ser enviados. Todas as solicitações de gravação pendentes serão concluídas, mas as solicitações de gravação subsequentes falharão. Além disso, um pacote FIN será enviado para outro lado para informar que não temos mais dados para enviar.
fonte
shutdown()
a conexão e, em seguida, ela não está mais viva. Você ainda tem o descritor de arquivo. Você ainda poderecv()
do buffer de recebimento. E você ainda precisa ligarclose()
para descartar o descritor de arquivo.Existem algumas limitações
close()
que podem ser evitadas se alguém as usarshutdown()
.close()
terminará as duas direções em uma conexão TCP. Às vezes, você deseja dizer ao outro terminal que concluiu o envio de dados, mas ainda deseja receber dados.close()
diminui a contagem de referência dos descritores (mantida na entrada da tabela de arquivos e conta o número de descritores atualmente abertos que se referem a um arquivo / soquete) e não fecha o soquete / arquivo se o descritor não for 0. Isso significa que, se você estiver bifurcando, a limpeza ocorre somente depois que a contagem de referência cai para 0. Com isso,shutdown()
é possível iniciar a seqüência normal de fechamento do TCP ignorando a contagem de referência.Os parâmetros são os seguintes:
int how
pode ser:SHUT_RD
ou0
Recebimentos adicionais não são permitidosSHUT_WR
ou1
Envios adicionais não são permitidosSHUT_RDWR
ou2
Mais envios e recebimentos não são permitidosfonte
Isso pode ser específico da plataforma, de alguma forma duvido, mas, de qualquer maneira, a melhor explicação que já vi está aqui nesta página do msdn, na qual eles explicam sobre desligamentos, opções remanescentes, fechamento de soquetes e seqüências gerais de terminação de conexão.
Em resumo, use shutdown para enviar uma sequência de desligamento no nível TCP e use close para liberar os recursos usados pelas estruturas de dados do soquete em seu processo. Se você não tiver emitido uma sequência de desligamento explícita no momento em que você fechar, uma será iniciada para você.
fonte
Eu também tive sucesso no linux usando
shutdown()
de um pthread para forçar outro pthread atualmente bloqueadoconnect()
para abortar mais cedo.Em outros sistemas operacionais (OSX pelo menos), achei que a chamada
close()
era suficiente paraconnect()
falhar.fonte
"shutdown () na verdade não fecha o descritor de arquivo - apenas altera sua usabilidade. Para liberar um descritor de soquete, você precisa usar close ()." 1
fonte
Perto
Quando você terminar de usar um soquete, você pode simplesmente fechar seu descritor de arquivo com close; Se ainda houver dados aguardando para serem transmitidos pela conexão, normalmente o close tenta concluir esta transmissão. Você pode controlar esse comportamento usando a opção de soquete SO_LINGER para especificar um período de tempo limite; consulte Opções de soquete.
Desligar
Você também pode desligar apenas a recepção ou transmissão em uma conexão chamando shutdown.
A função de desligamento desliga a conexão do soquete. Seu argumento como especifica qual ação executar: 0 Pare de receber dados para esse soquete. Se mais dados chegarem, rejeite-os. 1 Pare de tentar transmitir dados deste soquete. Descartar todos os dados que aguardam para serem enviados. Pare de procurar confirmação de dados já enviados; não o retransmita se estiver perdido. 2 Pare a recepção e a transmissão.
O valor de retorno é 0 em caso de sucesso e -1 em caso de falha.
fonte
no meu teste.
close
enviará pacotes fin e destruirá o fd imediatamente quando o soquete não for compartilhado com outros processosshutdown
SHUT_RD , o processo ainda pode recuperar os dados do soquete, masrecv
retornará 0 se o buffer TCP estiver vazio. Depois que o par enviar mais dados,recv
os dados retornarão novamente.shutdown
SHUT_WR enviará pacotes fin para indicar que os envios adicionais não são permitidos. o par pode recuperar dados, mas recuperará 0 se seu buffer TCP estiver vazioshutdown
SHUT_RDWR (igual a usar SHUT_RD e SHUT_WR ) enviará o primeiro pacote se os pares enviarem mais dados.fonte
close()
enviei o RST no Linux em vez do FIN.recv()
eles retornam dados novamente' não está correto. 2. O comportamento se o par enviar mais dados depoisSHUT_RD
depende da plataforma.