はじめに
開発中のコンテナ内で動いている開発サーバー(ポート5174)に別のホストからアクセスするために、socat(ネットワーク用語:2つの通信経路の間でデータを中継するコマンド)で次のようにポートを中継しています。
socat TCP-LISTEN:5174,fork,reuseaddr TCP:claude-wt-bristleworm:5174
この中の reuseaddr は「socatを再起動した直後でも、同じポート番号ですぐに待ち受けられるようにする指定」です。
この記事では、reuseaddr がないと何が起きるのか、なぜ必要なのかを整理します。
問題:reuseaddrが無い場合
reuseaddr を付けずにsocatを起動し、ブラウザから接続している状態でsocatを止めてすぐに起動し直すと、次のようなエラーで起動に失敗することがあります。
Address already in use
「ポートがすでに使用中」という意味ですが、socatはもう止めているので、使っているプロセスはいないはずです。しばらく待つと、同じコマンドで普通に起動できるようになります。
原因:TIME_WAIT
原因は、直前まで使っていた接続が TIME_WAIT(TCP用語:接続を閉じたあと、遅れて届くデータに備えて一定時間その接続の情報を残しておく状態)で残っているためです。
TCPでは、先に接続を閉じた側にTIME_WAITが残ります。socatを止めると、socatの側からブラウザとの接続を閉じることになるので、ポート5174の接続がTIME_WAITとして残ります。
Linuxではこの状態が約60秒続き、その間は reuseaddr なしだと同じポート番号で待ち受けられません。
TIME_WAITが残っているかどうかは、次のコマンドで確認できます。
ss -tan | grep 5174
TIME-WAIT と表示される行があれば、それが原因です。
なお、直前に接続が1本もなかった場合など、TIME_WAITが残っていなければ reuseaddr なしでもすぐ起動できます。「いつもは起動できるのに、たまに失敗する」という分かりにくい動きになるのはこのためです。
解決方法:reuseaddrがある場合
reuseaddr を付ける
reuseaddr を付けると、TIME_WAITの接続が残っていてもそのポートで待ち受けられるようになります。
socat TCP-LISTEN:5174,fork,reuseaddr TCP:claude-wt-bristleworm:5174
これはLinuxのソケットオプション SO_REUSEADDR を有効にする指定です。開発中に何度もsocatを止めたり起動したりする場合は、付けておくと待ち時間がなくなります。
reuseaddr でも同時に待ち受けはできない
reuseaddr が許すのは「TIME_WAITで残っている接続があってもポートを使う」ことだけです。
別のsocatがすでに同じポートで待ち受けている場合は、reuseaddr を付けていても2つ目は Address already in use で起動に失敗します。たとえば、1つ目のsocatを止め忘れたまま同じコマンドをもう一度実行すると、2つ目はエラーになります。
同じポートで待ち受けるプロセスが1つに限られるおかげで、どちらに接続が届くか分からない状態にならずに済んでいます。
同じポートで複数のプロセスを同時に待ち受けさせたい場合は、別の指定である reuseport(Linuxのソケットオプション SO_REUSEPORT に対応。複数プロセスで同じポートを共有し、届いた接続をOSが振り分ける)を使います。
| 指定 | できること |
|---|---|
| なし | TIME_WAITが残っている間は待ち受けできない |
reuseaddr |
TIME_WAITが残っていても待ち受けできる。ただし待ち受け中の別プロセスがいれば失敗する |
reuseport |
複数のプロセスで同じポートを同時に待ち受けできる |
おわりに
reuseaddr がないと、socatを再起動した直後に、TIME_WAITのせいで約60秒ほど同じポートが使えなくなることがあります。
- 再起動してすぐ使いたい →
reuseaddrを付ける - 止め忘れたsocatとの重複起動は
reuseaddrでも防がれる - 同じポートを複数プロセスで共有したい →
reuseport
開発中に何度も止めたり起動したりするポート中継では、reuseaddr を付けておくのが無難です。
参考
JISOUのメンバー募集中!
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてください!
▼▼▼
https://projisou.jp
