TIME_WAITとBindExceptionの抑制

先日のエントリで書いた不具合は、兎にも角にもソケットを激しくオープン/クローズ(バインド/アンバインド)した結果、再利用できないTIME_WAIT状態のソケットが大量に発生することで起こったことだ。WindowsプラットホームであればTCPソケット関連のレジストリエントリを書き換えることで対応したが、そもそもTIME_WAIT状態のソケットを早々に使いまわすことはできないのだろうか。

  • SO_REUSEADDR

TCPソケットを生成するソケットAPIを実装又はラップする言語で同名、又は同様のオプションで見たことがあるだろう。このソケットオプションをオンにした後にバインドされたソケットは、接続が完了してTIME_WAIT状態になっても強制的にバインドができるようになる。

JavaのServerSocketクラスによるSO_REUSEADDRオプションの設定

ServerSocket socket = new ServerSocket();
socket.setReuseAddress(true);

.NET(C#)のSocketクラスによるSO_REUSEADDRオプションの指定

Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);

これを使えば良さそうだが、あくまでこれはサーバ側での話。サーバの実装が判っていてソースコードまで弄れるのであればこれを試すのが良さそうだが、よくあるサーバ側がブラックボックスの場合は実装を修正することは不可能だ。それに、どんなアプリケーションであっても常時SO_REUSEADDRオプションを有効にしておくのが良いとは限らないし。

なお、このSO_REUSEADDRオプションだが「Win32プラットホームでは使っちゃ駄目」というのがコモンセンスになっているようだ。私が無知なだけなのだろうが理由は何なのだろう。バグがあるからとかか。