web-dev-qa-db-ja.com

長さが0のデータを返すrecv()ソケット関数

別のデバイス(Webサーバーを備えたハードウェアデバイス)とのポート番号5005でソケット接続を確立するアプリケーションがあります。

ハードウェアデバイスが切断されると、デバイスとの接続が失われます。

  1. これは、今まで使っていたソケットが無効になるということですか?.

  2. この切断が発生したときに、ヌル文字などの特別なメッセージが表示されますか?.

  3. ソケット接続iが無効になった場合、recv()ソケット関数がSOCKET_ERRORをスローしないのはなぜですか。代わりに、長さが0のデータを受け取るのはなぜですか。

ありがとう

18
ckv

recvが値0を返す場合、接続が閉じられたことを意味します。

recvのマニュアルページ: を参照してください。

これらの呼び出しは、受信したバイト数、またはエラーが発生した場合は-1を返します。ピアが正常なシャットダウンを実行すると、戻り値は0になります。

質問1の回答として、はい、ソケットは無効になっています。さらに通信するには、新しいソケットと接続を作成する必要があります。

編集

Valdoが以下で指摘しているように、半分閉じたTCP接続では、これ以上受信できませんが、受信するまでソケットに書き込みを続けることができます。データの送信が終了しました。詳細については、次の記事を参照してください: TCP Half-Close 。ただし、このような状況ではないようです。

質問2の回答として、閉じたソケットを検出する方法は基本的に2つあります。これは、ソケットが正常にシャットダウンされたこと、つまりピアがshutdownまたはcloseと呼ばれることを前提としています。

最初の方法は、ソケットから読み取ることです。この場合、戻り値は0になります。もう1つの方法は、ソケットに書き込むことです。これにより、パイプの破損を示すSIG_PIPE信号がスローされます。

シグナルを回避するために、MSG_NOSIGNALソケットオプションを設定できます。この場合、 send は-1を返し、errnoEPIPE

35

ロバートS.バーンズに同意します。ソケットが「無効」になっているという主張を除いて。

それはまだ有効です。あなたはそれを使うことができます。ピアにデータを送信することもできます。それでできない唯一のことはrecvを呼び出すことです。

9
valdo

Recvが0を返す場合、これはピアがソケットを閉じたことを意味します。

recvはC関数であるため、スローされません。

エラーがある場合、recvは-1を返します。その場合、アプリケーションはエラーのタイプをチェックする必要があります。 -1が返されたからといって、ピアがソケットを閉じたことを意味するわけではないことに注意してください。

2
sashang

TCPを使用してデバイスと通信していると思います。

  1. ソケット自体はまだ「有効」ですが、接続が失われました。

  2. 他のホストによって接続が閉じられた場合、recv()の戻り値は0になります(この切断が正常であったかどうかは関係ありません)。

  3. ソケット関数はC関数に似ています。例外が存在するCプログラムで使用できるため、スローされませんnot

2
ereOn

Webサーバーと通信しているとすると、TCPソケットを使用していると想定します。

答える:

  1. 切断によってソケットが無効になることはありません。それらは単に切断状態になります。それらに対してソケット操作を呼び出すことは依然として安全です。

  2. 切断が発生しても、特別なメッセージは表示されません。 recv()をブロック方式で呼び出すと、切断されたときに返され、呼び出しから返されるバイト数は、要求したバイト数と一致しません。

  3. これに対する答えは実際にはありません-ソケットAPIが最初に実装された方法であり、全員がバークレーソケットを実装しているため、その実装に固執しています。

1
Blair Holloway

既存の回答の多数の虚偽表示を修正するには:

  1. これは、今まで使っていたソケットが無効になるということですか?.

いいえ。これは、ピアが接続を閉じたか、接続をシャットダウンして自分の側から出力したことを意味します。ソケットはまだ有効です。もう一度recv()を呼び出すことができますが、取得できるのは別のゼロだけです。その上でsend()を呼び出すこともでき、ピアが出力のために接続をシャットダウンしただけの場合、データが送信されます。

  1. この切断が発生したときに、ヌル文字などの特別なメッセージが表示されますか?.

いいえ、recv()からゼロの戻り値を取得します。それが目的です。データバッファではなく、帯域外で配信されます。

  1. ソケット接続が無効になった場合、なぜrecv()ソケット関数がスローされないのですか?

これはCAPIであり、CにもUni​​xシステムコールにもthrowsがないためです。

およびSOCKET_ERROR。

エラーではないからです。

代わりに、長さが0のデータを受け取るのはなぜですか。

'長さ0のデータを受信しません'。ゼロの戻り値を受け取ります代わりにデータ。

1
user207421