非ブロッキングrecvが0を返したときにどのケースが発生するかを知る方法は?
非ブロッキングソケットで実行される単純なTCPサーバーがあります。
recvのマンページからの引用;
ストリームソケットピアが正常なシャットダウンを実行すると、戻り値は0になります(従来の「ファイルの終わり」の戻り値)。
ストリームソケットから受信するように要求されたバイト数が0の場合も、値0が返されることがあります。
ソケットが読み取り可能になったら、次のコードで読み取ります。
uint8_t buf[2048];
ssize_t rlen;
while(1){
rlen = recv(fd, buf, sizeof(buf), 0);
if(rlen < 0){
/* some error came, let's close socket... */
}
else if(rlen == 0){
/* is there no bytes to read? do we need break; in here? */
/* is socket closed by peer? do we need to close socket? */
}
/* some code that process buf and rlen... */
}
recv
0を返すときにどのケースが発生するかをどのように知ることができますか?
回答
recv
0を返す場合は、ソケットが他のピアによって正常に閉じられており、自分の側からも閉じることができることを意味します。ソケットにデータが存在しない場合、-1が返さerrnoれ、EAGAIN
/に設定されETIMEDOUT
、ソケットを閉じる必要はありません。
最後に、-1が返され、とerrno
は異なる値に設定された場合、EWOULDBLOCK
またはEAGAIN
ソケットを閉じる必要がある場合。これは、回復不能なエラーが発生したためです。
非ブロッキングソケットの場合、recv
が呼び出されたときにすぐに利用できるデータがないことを意味します。ソケットをブロックする場合SO_RCVTIMEO
)は、以前にsetsockopt()
有効期限が切れて設定されたタイムアウト()の後でも、データが利用できないことを意味します。
前回の編集で正しく引用したrecv
ように、要求されたサイズが0の場合も、から0を返すことができます。
recvが0を返したときにどのケースが発生するかをどのように知ることができますか?
提供されたrecvサイズをテストするだけです(この場合は定数配列のサイズなので、あまり意味がありませんが、他の場所からの変数の場合は...):
bufSize = sizeof(buf);
/* further code that, who knows, might affect bufSize */
rlen = read(fd, buf, bufSize);
if(rlen < 0){
if (errno != ETIMEDOUT && errno != EWOLUDBLOCK)
{
/* some error came, let's close socket... */
}
}
else if(rlen == 0){
if (bufSize != 0)
{
/* Close socket */
}
}