2012-01-03 5 views
9

ローカルのlinuxホストのTCPソケットがリモートホストと接続状態にあるとします。ローカルホストは、epoll_waitを使用して、リモートホストとのソケットのイベントを通知しています。リモートホストが呼び出しした場合Epollとリモートの一方向シャットダウン

shutdown(s,SHUT_WR); 

をその接続されたソケットに送信することが行われて示すために、どのようなイベント(複数可)そのソケットのローカルホスト上のリターンをれるepoll_waitでしょうか?

私はEPOLLINが常に返されると仮定しています。その後のrecv呼び出しは、リモート側が送信を完了したことを示すために0を返します。

EPOLLHUPまたはEPOLLRDHUPはどうですか? (そして、これら2つのイベントの違いは何ですか?)

さらにEPOLLERR?

リモートホストが「シャットダウン」ではなく「閉じる」を呼び出す場合は、上記のいずれかの答えが変わりますか?

答えて

18

私は答えを見つけるために重い持ち上げをした後、この自分自身に答えています。

epollイベントをリスンするソケットは、通常、closeまたはshutdown(SHUT_WR)を呼び出すリモートピアでEPOLLRDHUP(EPOLLINに加えて)イベントフラグを受信します。これは必然的にソケットが死んでいることを意味するわけではありません。その後のrecv()の呼び出しは、ソケット上の未読データを返し、最終的にEOFを示すために "0"が返されます。リモートピアがソケットの半分しか閉じなかった場合、データを返すことさえ可能かもしれません。

注目すべき例外は、リモートピアがソケットで有効になっているSO_LINGERオプションを使用していて、リンガー値が「0」の場合です。そのようなソケットを閉じた結果、FINの代わりにTCP RSTが送信される可能性があります。私が読んだことから、接続リセットイベントはEPOLLHUPまたはEPOLLERRのいずれかを生成します。 (私は確認する時間がなかったが、意味がある)。

EPOLLHDUPをサポートしない古いLinux実装があると示唆しているドキュメントがあります。そのようなEPOLLHUPが代わりに生成されるためです。

私の特別なケースでは、EPOLLHUPイベントやEPOLLRDHUPイベントのコードを書くのはあまり面白くないことがわかりました。代わりに、これらのイベントをEPOLLIN/EPOLLOUTと同じように扱い、recv()(またはsend()を適切に呼び出す)を呼び出してください。しかし、recv()とsend()から返された戻りコードに細心の注意を払ってください。

+1

ここでの動作に関する質問が多かったので、私はこれらのやりとりについて詳しく説明しました:https://medium.com/where-the-flamingcow-roams/down-the-epoll-rabbit-hole-5c0447cb6329 – flamingcow

関連する問題