SO_RCVTIMEOとSO_SNDTIMEOで設定された2つのsetsockoptでタイムアウトした後に切断するマルチスレッドLinux TCPサーバーにソケットを実装する必要があります。recvは、クライアントクラッシュ時に-1の代わりに0を返します。
ここでは、コードです:
if(setsockopt(receive_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout))<0){
printf("errore sock option rcvtimeo\n");
exit(EXIT_FAILURE);
}
if(setsockopt(receive_sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout))<0){
printf("errore sock option sndtimeo\n");
exit(EXIT_FAILURE);
}
このソケットに関連するスレッドの産卵後、サーバはこの機能を持つのrecvにとどまる:
int receive_message(int descriptor, char* buffer){
memset(buffer,0,sizeof(buffer));
int ret;
while((ret= recv(descriptor, buffer, BUFFER_SIZE-1, MSG_NOSIGNAL))<=0){
if (errno == EWOULDBLOCK || errno == EPIPE){
//stuff...
pthread_exit(NULL);
}
else if (errno == EINTR) continue;
else exit(EXIT_FAILURE);
}
buffer[ret]= '\0';
return ret;
}
クライアントがオンラインのままの場合が、ノーとは応答では、if(errno == EWOULDBLOCK || errno == EPIPE)文で正しく終了しますが、クライアントがクラッシュしたり終了したりすると、receiveのret値はwhileループではなく永遠に0になります。 1またはEWOULDBLOCK。
どうすれば解決できますか?
「0」をチェックしてそれを処理しますか?マニュアルページ:*「TCPソケットの場合、戻り値0はピアが接続の半分を閉じたことを意味します」* – user3386109
クライアントがクラッシュすると、recvは-1を返すと考えました。私のせいで、ありがとう! – gabrielication
BTW: 'memset(buffer、0、sizeof(buffer));はカーゴカルトプログラミングです。そして、errnoはrecv()が-1を返した後にのみ有効です。 > 0を返すrecv()では、errnoに意味のある値はありません。 – wildplasser