操作して学ぶ
状態遷移(FSM)可視化
いまの状態と起きたイベントだけで次が決まる—— これが有限オートマトン(状態機械)です。イベントのボタンを押して、実際に状態を歩いてみてください。 本命はTCPの接続状態。ss や netstat で見かけるCLOSE_WAIT と TIME_WAIT が、 どの経路で現れるのかが分かります。
ソケットが辿る状態。ss や netstat で見える CLOSE_WAIT / TIME_WAIT が、どの経路で現れるのかを追えます。左半分が接続確立、右半分が切断。
現在の状態CLOSED
接続なし。すべての始まりであり終わり。
ここから起こせるイベント(2)
たどった経路
CLOSED
TCPで実務的に効く3点
- CLOSE_WAIT が溜まっていたら自分側のバグ。相手のFINを受けてACKを返した後、アプリが
close()を呼ぶまでここから動きません。 大量に滞留するのは「接続を閉じ忘れている」証拠で、FD枯渇へ直行します。図でESTABLISHED → CLOSE_WAITと進めると、次のイベントが自分の close() しか無いことが見えます。 - TIME_WAIT が大量にあるのは普通。先に閉じた側(能動クローズ)が最後に通る状態で、2MSL待ってから消えます。 遅れて届いた古いパケットが、同じポートで張り直した次の接続に混ざるのを防ぐ意図的な猶予。 異常ではないので、闇雲に短縮するのは危険です。
- 「どちらが先に閉じたか」で通る道が違う。能動クローズは
FIN_WAIT_1 → FIN_WAIT_2 → TIME_WAIT、 受動クローズはCLOSE_WAIT → LAST_ACK。同じ「切断」でも状態列が非対称なのがTCPの肝です。
状態機械は通信プロトコルだけのものではありません。注文・予約・ジョブの進行、UIの画面遷移、パーサ——「取りうる状態」と「許される遷移」を先に決めると、if の山が消え、ありえない組み合わせを型や構造で排除できます。