91

ピア側のソケットが閉じられたときに壊れたパイプのエラーがスローされることを知っています。

しかし、私のテストでは、ピア側が閉じているときにこちら側で即時の「送信」呼び出しを行っても、必ずしもパイプの破損エラーが発生するとは限らないことに気付きました。

例えば:

ピア側でソケットを閉じた後 (close を呼び出してクリーン クローズを試み、ピアを強制終了して異常なクローズを試みました)、40 バイトを送信しようとすると、パイプが壊れることはありませんが、 40000バイトを送信すると、すぐに壊れたパイプエラーが発生します。

壊れたパイプの正確な原因とその動作を予測できますか?

4

4 に答える 4

67

ネットワークのクローズが観察されるまでに時間がかかる場合があります。クローズ後、ポート宛てのパケットがすべて無効であると見なされるまでの合計時間は、名目上約 2 分 (そうです、数分!) です。エラー状態は、ある時点で検出されます。小さな書き込みでは、システムの MTU 内にいるため、メッセージは送信のためにキューに入れられます。大きな書き込みでは、MTU よりも大きくなり、システムは問題をより迅速に特定します。SIGPIPE シグナルを無視すると、壊れたパイプで関数が EPIPE エラーを返します - 接続の壊れた状態が検出されたある時点で。

于 2011-01-03T16:55:52.427 に答える
13

ソケットの現在の状態は、「キープアライブ」アクティビティによって決定されます。あなたの場合、これは、send呼び出しを発行しているときにkeep-alive、ソケットがアクティブであることをアクティビティが通知する可能性があるため、send呼び出しは必要なデータ (40 バイト) をバッファーに書き込み、エラーを発生させずに戻ります。

より大きなチャンクを送信している場合、send 呼び出しはブロッキング状態になります。

send の man ページでもこれが確認されています。

メッセージがソケットの送信バッファーに収まらない場合、send() は、ソケットが非ブロッキング I/O モードに設定されていない限り、通常はブロックします。非ブロッキング モードでは、この場合 EAGAIN が返されます。

そのため、使用可能な空きバッファをブロックしているときに、発信者が (キープアライブ メカニズムによって) もう一方の端が存在しないことを通知されると、送信呼び出しは失敗します。

上記の情報では正確なシナリオを予測することは困難ですが、これが問題の原因であると私は信じています.

于 2011-01-03T17:43:26.567 に答える
4

40 バイトはパイプ バッファに収まり、40000 バイトは収まらないのでしょうか。

編集:

閉じたパイプに書き込もうとすると、送信プロセスに SIGPIPE シグナルが送信されます。シグナルがいつ送信されるのか、パイプ バッファがこれにどのような影響を与えるのか、正確にはわかりません。sigaction 呼び出しでシグナルをトラップすることで回復できる場合があります。

于 2011-01-03T13:47:53.693 に答える