O envio do TCP não retorna porque o processo de travamento
Pergunta
Se um servidor e cliente TCP estiverem conectados, gostaria de determinar quando o cliente não está mais conectado. Eu pensei que posso simplesmente fazer isso tentando enviar uma mensagem para o cliente e, uma vez se enviar (), retorna com -1, posso derrubar o soquete. Essa implementação funciona no Windows, mas no minuto em que tento fazer isso no Linux com soquetes BSD, a chamada para enviar () no aplicativo do lado do servidor faz com que o aplicativo do meu servidor trave se o cliente não estiver mais conectado. Nem retorna um -1 ... apenas encerra o programa.
Por favor, explique por que isso está acontecendo. Desde já, obrigado!
Solução
Isso é causado pelo sinal Sigpipe. Ver send(2)
:
A função send () deve falhar se:
Epipe] O soquete é desligado para escrever ou o soquete é o modo de conexão e não está mais conectado. No último caso, e se o soquete for do tipo Sock_stream ou Sock_seqpacket e o sinalizador msg_nosignal não será definido, o sinal Sigpipe é gerado para o encadeamento de chamada.
Você pode evitar isso usando o MSG_NOSIGNAL
bandeira no send()
ligue, ou ignorando o SIGPIPE
sinal com signal(SIGPIPE, SIG_IGN)
no início do seu programa. Então o send()
A função retornará -1 e definirá errno
para EPIPE
nesta situação.
Outras dicas
Você precisa ignorar o sinal Sigpipe. Se um erro de gravação ocorrer em um soquete, seu processo com o GET SIGPIPE e o comportamento padrão desse sinal é matar seu processo. Escrevendo o código de rede em *nix que você geralmente deseja:
signal(SIGPIPE,SIG_IGN);