回答:
/etc/init.d/networking restart
詳しく説明させてください。Transmission Control Protocol(TCP)は、2つのエンドポイント(プログラム)間の双方向の、順序付けられた、信頼性の高いデータ伝送プロトコルとして設計されています。このコンテキストでは、信頼できるという用語は、途中でパケットが失われた場合にパケットを再送信することを意味します。TCPは、ピアから受信した単一または一定範囲のパケットに対して確認応答(ACK)パケットを送り返すことにより、信頼性を保証します。
これは、終了要求/応答などの制御信号でも同じです。RFC 793では、TIME-WAIT状態が次のように定義されています。
TIME-WAIT-リモートTCPが接続終了要求の確認応答を受信したことを確認するのに十分な時間待機することを表します。
次のTCP状態図を参照してください。
TCPは双方向通信プロトコルであるため、接続が確立されると、クライアントとサーバーの間に違いはありません。また、どちらかが終了を呼び出すことができ、確立されたTCP接続を完全に閉じるには、両方のピアが閉じることに同意する必要があります。
終了をアクティブなクローザーと呼び、他のピアをパッシブなクローザーと呼ぶ最初のものを呼び出しましょう。アクティブクローザーがFINを送信すると、状態はFIN-WAIT-1になります。次に、送信されたFINのACKを受信し、状態はFIN-WAIT-2になります。パッシブクローザーからもFINを受信すると、アクティブクローザーはACKをFINに送信し、状態はTIME-WAITになります。パッシブクローザーが2番目のFINへのACKを受信しなかった場合、FINパケットを再送信します。
RFC 793は、タイムアウトを最大セグメント寿命の2倍、つまり2MSLに設定します。パケットがインターネットをさまようことができる最大時間であるMSLは2分に設定されているため、2MSLは4分です。ACKに対するACKがないため、アクティブなクローザーは、TCP / IPプロトコルに正しく準拠している場合、パッシブ送信者がそのFINへのACKを受信していない場合(理論的に)、4分間待つ以外に何もできません。
実際には、パケットの欠落はおそらくまれであり、すべてがLAN内または単一のマシン内で発生している場合は非常にまれです。
「TIME_WAITでソケットを強制的に閉じる方法」という逐語的な質問に答えるために、元の答えに固執します。
/etc/init.d/networking restart
実際には、WMRが述べたようにSO_REUSEADDRオプションを使用してTIME-WAIT状態を無視するようにプログラムします。 SO_REUSEADDRは正確に何をしますか?
このソケットオプションは、このポートがビジー(
TIME_WAIT状態)であっても、先に進み、とにかく再利用するようカーネルに指示します。それがビジーであるが、別の状態では、まだ使用中のエラーのアドレスが表示されます。サーバーがシャットダウンされ、ポートでソケットがまだアクティブな間にすぐに再起動された場合に便利です。予期しないデータが入った場合、サーバーが混乱する可能性があることに注意する必要がありますが、これは可能ですが、可能性は低いです。
/etc/init.d/networking
はプラットフォーム固有(Debian?)であるため、他のシステムでは正確なコマンドラインが(場合によってはかなり根本的に)異なります。私は他のコメント者に同意しますが、これは深刻な行き過ぎであり、関連のないネットワークサービスにとって明らかに破壊的であるように見えます。
あなたが実行している特定のプログラムのソースコードを持っているかどうかはわかりませんが、そうであれば、SO_REUSEADDRを設定するだけでsetsockopt(2)
、ソケットがTIME_WAIT状態であっても同じローカルアドレスにバインドできますソケットはアクティブにリッスンしていますsocket(7)
。
TIME_WAIT状態の詳細については、UnixソケットFAQを参照してください。
SO_REUSEADDR
はソケットを「閉じません」。すでに開いているものを再利用できるようにするだけです。したがって、質問は「ソケットを強制的に閉じる方法TIME_WAIT
」です。
SO_REUSEADDR
できるようになるbind()
進みます。ただし、そのソケットをリッスンする場合は、すべて同じものlisten()
を返しEADDRINUSE
ます。言い換えれば、この回答は、一時ポートを使用するクライアントソフトウェアに役立つ可能性がありますが、サーバーソフトウェアの問題を解決するものではありません。
私の知る限り、プログラムに適切なシグナルハンドラを記述する以外に、ソケットを強制的に閉じる方法はありませんが、タイムアウトにかかる時間を制御する/ procファイルがあります。ファイルは
/proc/sys/net/ipv4/tcp_tw_recycle
これを行うことにより、タイムアウトを1秒に設定できます。
echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
ただし、このページには、この変数を設定する際の信頼性の問題に関する警告が含まれています。
関連ファイルもあります
/proc/sys/net/ipv4/tcp_tw_reuse
TIME_WAITソケットを(おそらくタイムアウトなしで)再利用できるかどうかを制御します。
ちなみに、カーネルのドキュメントでは、「技術専門家のアドバイス/リクエスト」なしにこれらの値を変更しないように警告しています。私はそうではありません。
プログラムは、ポート49200へのバインドを試行し、ポートがすでに使用されている場合は1ずつ増分するように作成されている必要があります。したがって、ソースコードを制御できる場合は、この動作を変更して、数秒待ってから、増分する代わりに同じポートで再試行することができます。
1
将来の接続で機能するように設定しますが、すでに開かれている現在の接続はどうですか?
別のオプションは、タイムアウトを0にしてSO_LINGERオプションを使用することです。この方法では、ソケットを閉じると強制的に閉じられ、FIN / ACKの閉じ動作に入る代わりにRSTが送信されます。これにより、TIME_WAIT状態が回避され、一部の用途により適している場合があります。
TIME_WAITは、ソケットプログラミングクライアントサーバーアーキテクチャで最も一般的な問題です。定期的に試行する数秒間待つのが最善の解決策です。サーバーを必要とするリアルタイムアプリケーションの場合、すぐに起動する必要がありますSO_REUSEADDRオプションがあります。
TIME_WAIT
サーバー上の」だけをスキップ代わりにそれに答えるの問題を避けるため最初の3つの答え。