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