0

libevent のドキュメントから、TCP セグメントがリモート ピアから受信されると、EV_READ イベントが生成されることがわかりました。次のシナリオで何が起こるか

  1. ソケットの読み取りイベントと書き込みイベントの両方に登録されているノンブロッキング アプリケーション
  2. シナリオ A : アプリケーションがイベントを待機しています。リモートからFINを取得し、EV_READイベントが生成され、アプリケーションが読み取り(またはrecv)を実行して0を取得します
  3. シナリオ B: アプリケーションがデータを送信しています。送信の実行に、リモートから FIN を取得します。アプリケーションは EPIPE を取得しますか (私はそう思います)。アプリケーションが EPIP を取得するのと同じ FIN に対して生成される EV_READ イベントもありますか?

関連する質問として、send と write がthisで言及されているように類似している場合、ECONNRESET がマニュアル ページhereのように write で生成されず、man ページhereで説明されているように send で生成されるのはなぜでしょうか。

ローカル送信が ECONNRESET を返すようにリモート ピアを作成するにはどうすればよいですか。回答ありがとうございます

4

1 に答える 1

3

シナリオ A : アプリケーションがイベントを待機しています。リモートからFINを取得し、EV_READイベントが生成され、アプリケーションが読み取り(またはrecv)を実行して0を取得します

はい、そうです。

シナリオ B: アプリケーションがデータを送信しています。送信が実行されている間に、リモートから FIN を取得します。アプリケーションは EPIPE を取得しますか (私はそう思います)。アプリケーションが EPIPE を取得するのと同じ FIN に対して生成される EV_READ イベントもありますか?

はい、EV_READ イベントが生成されます。(もちろん、その間にソケットを close() しなかった場合)。

ただし、この非常に特殊なケースでは、書き込み時にエラーは発生しません。ピア エンドから FIN を取得すると、TCP 接続は半分だけ閉じられます。着信 FIN は、単に「送信するものが何もない」ことを意味します。ただし、より多くのデータを送信できます。または、ソケットを close() して、自分の側からピアに FIN を送信すると、両方とも FIN パケットを送信したため、TCP 接続が閉じられたと見なされます。

この時点で、close() または shutdown() を呼び出したかどうかは、ピアが実際に何をしたかによって異なります。後続の write() で、ピア アプリケーションがソケットを閉じてピアが RST を送信した場合は EPIPE または ECONNRESET を取得するか、ピアがより多くのデータを受信するようにコーディングされている場合はデータを送信し続ける可能性があります。

特定のケースを説明しているだけであることに注意してください。タイミングと、ネットワークまたはピアで何が起こっているかに応じて、考慮すべきケースはさらに多くあります。

ローカル送信が ECONNRESET を返すようにリモート ピアを作成するにはどうすればよいですか。

これは、ピアのローカル バッファに読み取るデータがまだあるときに、ピアが close() を実行した場合に発生します。その場合、RST が送信され、read()/recv() と同様に、書き込み/送信は ECONNRESET でエラーになります。

このケースを生成するには、何も read() しないで、データが到着したことを確認するまで少し待ってから、ソケットを close() します。反対側で後で write() を実行すると、ECONNRESET が取得されます。そして、ECONNRESET の後の別の write() は EPIPE を取得する必要があります。

于 2013-06-28T17:52:35.653 に答える