1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

socatのreuseaddrが必要な理由

1
Posted at

はじめに

開発中のコンテナ内で動いている開発サーバー(ポート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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?