1

状況は次のとおりです。A と B の 2 台のマシンがあります。A はポート p をリッスンします。B はソケット s1 を作成し、p に接続します。A はソケット s2 で接続を受け入れます。今のところ、A と B はソケットを介して相互に通信できます。

ただし、A でプログラムを強制終了し、しばらくしてからこのプログラムを再起動すると、B はこの期間中に A にデータを送信していないため、わかりません。ここで、B は s1 を介して A にデータを書き込み始めます。次は何が起こるのだろう?なんで?

実際、write呼び出しは失敗していないことがわかりましたが、A はまだデータを取得していません。さらに、s1 を epoll デバイスに入れると、 によって返されるイベントepoll_waitEPOLLERR | EPOLLHUPへの呼び出しの後であることがわかりましたwrite。なんで?

残念ながら、この状況では、「書き込み」呼び出しは失敗しなかったが、A はデータを取得できなかったため、データを失ったように見えます。解決策はありますか?

4

3 に答える 3

2
  1. ソケットを確立したプログラムを強制終了すると、他のすべての端末に RST が送信されます。したがって、B は s1 で RST を受信する必要があり、s1 での以降の呼び出しはすべてエラーを返します。ただし、一部のファイアウォールは RST パケットを除外する場合があります。RST パケットは tcpdump で確認できます。

  2. B がステップ 1 で RST パケットを受信しない場合、B が他のパケットを A に送信 (書き込み) し続けると、A は RST パケットで応答し、B がこの RST を受信すると、B に対する以降の呼び出しはすべてエラーを返します。

  3. ステップ 2 でも B が RST パケットを受信しない場合、一定時間 (書き込みタイムアウト) が経過した後、B は接続を切断し、B に対する今後のすべての呼び出しでエラーが返されます。

ご覧のとおり、書き込み呼び出しはめったにエラーを返しません。パケットが送信された場合は成功を返し、リモート エンドがパケットを受信するかどうかは気にしません。

あなたの状況では、epoll_wait を呼び出すとすぐに EPOLLHUP を取得しませんが、RST または書き込みタイムアウトを受信した後

于 2012-08-20T05:29:32.380 に答える
1

切断されたストリームに書き込みました (マシンが切断されたことを知らなかったとしても。「接続を受け入れる」と言うので、2 台のマシン間に TCP 接続を設定していると思います。)

UDP について話している場合、Listen/Connect/Accept はなく、データは addr/port でリッスンしているものに送信されます。しかし、あなたはUDPについて話しているのではありません。[結論を説明するために編集:] 切断された接続にデータを書き込んでいます (そして、接続を使用しようとしたので、ある時点で接続が切断されていることが明らかになります)。データの書き込みは、反対側がデータを受信したかどうかを示しません。成功は、送信するデータをキューに入れたことを示します。

于 2012-08-20T05:20:31.417 に答える