これについてはSEに関する質問がかなりあることは知っていますが、ここまで来る前に重要な質問をたくさん読んだと思います。
「サーバー側TIME_WAIT
」とは、サーバー側でclose()が開始されたサーバー側ソケットペアの状態を意味します。
私はしばしば私には矛盾しているように見えるこれらの声明を見ます:
- サーバー側
TIME_WAIT
は無害です - クライアントがclose()を開始するようにネットワークアプリを設計する必要があります。したがって、クライアントに
TIME_WAIT
私がこの矛盾を見つける理由はTIME_WAIT
、クライアント上で問題が発生する可能性があるためです-クライアントは利用可能なポートを使い果たす可能性があるため、本質的には、上記のTIME_WAIT
問題は、クライアント側に問題がある可能性がある負荷をそれは問題ではないサーバー側。
クライアント側TIME_WAIT
はもちろん、限られた数のユースケースでのみ問題になります。ほとんどのクライアントサーバーソリューションには、1台のサーバーと多数のクライアントが関係します。クライアントは通常、問題になるほど十分な量の接続を処理しません。SO_LINGER
タイムアウトが0の場合や、tcp_tw sysctlを調整するのとは対照的に)TIME_WAIT
あまりにも多くの接続を作成しすぎないようにして、クライアント側と戦います。しかし、たとえば次のようなアプリケーションのクラスでは、常に実行可能であるとは限りません。
- 監視システム
- 負荷発生器
- 代理人
反対に、サーバー側TIME_WAIT
がどのように役立つかさえもわかりません。理由TIME_WAIT
はそこにもありTCP
ます。それは、もはや属していないストリームに古いフラグメントを注入することを防ぐためです。クライアント側TIME_WAIT
ではip:port
、この古い接続が持つことができたのと同じペアで接続を作成することを単に不可能にすることで達成されます(使用されたペアはによってロックアウトされますTIME_WAIT
)。しかし、サーバー側の場合、ローカルアドレスには受け入れポートがあり、常に同じであり、サーバーは(私の知る限り、経験的証明しかありません)接続を拒否できないため、これを防ぐことはできません着信ピアは、ソケットテーブルにすでに存在する同じアドレスペアを作成します。
サーバー側のTIME-WAITが無視されることを示すプログラムを作成しました。さらに、テストは127.0.0.1で行われたため、カーネルには、サーバー側かクライアント側かを示す特別なビットが必要です(そうでなければ、タプルは同じになるため)。
ソース:http : //pastebin.com/5PWjkjEf、Fedora 22でテスト、デフォルトのネット設定。
$ gcc -o rtest rtest.c -lpthread
$ ./rtest 44400 s # will do server-side close
Will initiate server close
... iterates ~20 times successfully
^C
$ ss -a|grep 44400
tcp TIME-WAIT 0 0 127.0.0.1:44400 127.0.0.1:44401
$ ./rtest 44500 c # will do client-side close
Will initiate client close
... runs once and then
connecting...
connect: Cannot assign requested address
したがって、サーバー側TIME_WAIT
では、まったく同じポートペアでの接続をすぐに正常に再確立でき、クライアント側TIME-WAIT
では、2回目の反復でconnect()
正しく失敗しました
要約すると、問題は2つあります。
- サーバー側は
TIME_WAIT
実際には何もしませんRFC
か? - サーバー
TIME_WAIT
が役に立たないため、クライアントがclose()を開始することが推奨されているのはなぜですか?
TIME_WAIT
です。