3

単純なネットワーク モデルを想定します。A は B への TCP 接続を正常に作成し、次のように相互に通信しています。

A <----------> B

A のプログラムが停止すると (コア ダンプなど)、B への RST パケットが発生することはわかっています。したがって、B の読み取り試行は EOF につながり、B の書き込み試行は SIGPIPE につながります。私は正しいですか?

ただし、A でネットワークが故障した場合 (ケーブル/ルーターの障害など)、B の読み取り/書き込み試行はどうなりますか? 私の状況では、すべてのソケットがノンブロッキングに設定されています。その結果、ネットワーク エラーを検出することはできませんか?

ところで、ソケットにhttp://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/SO_KEEPALIVEに役立つオプションがあることに気付きました。しかし、プロービング間隔を 2 ~ 3 秒 (デフォルトでは 75 秒) に設定すると、どのくらいのコストがかかるのだろうか? そして、間隔構成はグローバルなもののようですが、これはマシン上のすべてのソケットに影響しますか?

最後の質問... ネットワークが故障し、書き込みを試みると、しばらくして EPIPE が発生するとします。しかし、書き込みを試みる代わりに、このソケットを epoll デバイスに挿入するとどうなるでしょうか? epoll_wait は EPOLLHUP または EPOLLERR イベントを返しますか?

4

2 に答える 2

7

TCP 接続が検出されずに停止する可能性がある他の多くの方法があります。

  • 誰かがネットワーク ケーブルを引き抜いています。
  • 反対側のコンピューターは核攻撃を受けます。
  • 間にある nat ゲートウェイは、サイレントに接続をドロップします
  • 反対側の OS が激しくクラッシュします。
  • FIN パケットが失われます。
  • 検出できないエラー: エンドポイント間のルーターがパケットをドロップする可能性があります (制御パケットを含む) reff

すべての場合において、プログラムの SIGPIPE エラーを介してソケットにこの原因を書き込もうとすると、それについて知ることができ、終了します。

read() では、相手が生きているかどうかを知ることはできません。ありがとう SO_KEEPALIVE 便利な理由。キープアライブは非侵襲的であり、ほとんどの場合、疑わしい場合は、何か間違ったことをするリスクなしにオンにすることができます. ただし、余分なネットワーク トラフィックが生成され、ルーターやファイアウォールに影響を与える可能性があることに注意してください。

そして、これはあなたのマシンのすべてのソケットにも影響します!(あなたは正しいです)。また、SO_KEEPALIVE はトラフィックを増加させ、CPU を消費するためです。アプリケーションが切断された接続に書き込む可能性がある場合は、SIGPIPE ハンドルを設定することをお勧めします。

また、アプリケーションの妥当な場所で SO_KEEPALIVE を使用します。接続期間全体で使用するのは不十分です (つまり、サーバーがクライアントのクエリで長時間動作する場合は、so_keepalive を使用します)。

プローブ間隔の設定は、アプリケーションに依存するか、アプリケーション層プロトコルと言います。

TCP キープアライブを有効にしても、最終的には検出されます。少なくとも数時間は検出されます。

ネットワークが故障したとしますが、書き込みを試みる代わりに、ソケットが epoll デバイスに置かれます:

epoll の 2 番目の引数:

 n = epoll_wait (efd, events, MAXEVENTS, -1);

正しいイベント関連コードを設定します。次のように、このコードを確認して
注意することをお勧めします。

n = epoll_wait (efd, events, MAXEVENTS, -1);  
for (i = 0; i < n; i++)  
{   
    if ((events[i].events & EPOLLERR) ||
          (events[i].events & EPOLLHUP) ||
          (!(events[i].events & EPOLLIN)))
    {
          /* An error has occured on this fd, or the socket is not
             ready for reading (why were we notified then?) */
      fprintf (stderr, "epoll error\n");
      close (events[i].data.fd);
      continue;
    }

    else if (sfd == events[i].data.fd)
    {
          /* We have a notification on the listening socket, which
         means one or more incoming connections. */
         
         // Do what you wants
     }
}

EPOLLRDHUPの 意味は次のとおりです:ストリーム
ソケット ピアが接続を閉じたか、接続の半分を書き込んでシャットダウンしました。(このフラグは、エッジ トリガー監視の使用時にピアのシャットダウンを検出する単純なコードを記述する場合に特に役立ちます。)

于 2012-10-10T05:54:08.747 に答える
4

A のプログラムが停止すると (コア ダンプなど)、B への RST パケットが発生することはわかっています。したがって、B の読み取り試行は EOF につながり、B の書き込み試行は SIGPIPE につながります。私は正しいですか?

部分的に。RST は、読み取り時に EOF ではなく ECONNRESET を発生させ、書き込み時には EPIPE を発生させます。

ただし、A でネットワークが故障した場合 (ケーブル/ルーターの障害など)、B の読み取り/書き込み試行はどうなりますか? 私の状況では、すべてのソケットがノンブロッキングに設定されています。その結果、ネットワーク エラーを検出することはできませんか?

select() などを介して読み取りタイムアウトを使用し、タイムアウトを失敗と見なさない限り、読み取りだけでは不可能です。書き込み時に最終的に EPIPE を取得しますが、バッファリングと再試行のために時間がかかり、何度か試行される可能性があります。

于 2012-10-10T03:56:21.760 に答える