TCPの状態遷移
TCPのコネクションが、確立から終了までの間にとる状態の移り変わり。LISTEN、ESTABLISHED、TIME-WAITなど11の状態がある。
イマシルちゃんの解説
TCPのコネクションには、「接続を待っているところ」「話しているところ」「お別れの挨拶をしているところ」みたいな状態があるんだ。
今どの状態にいるかで、次に何を受け取ったら、どの状態に移るかが決まってるんだよ。
ちょっと数は多いけど、つなぐときと切るときの流れで覚えればだいじょうぶ!
より深い解説
定義
TCPは、コネクションごとに状態を持ち、送受信したセグメント(SYN、ACK、FINなど)に応じて状態を変える。状態の一覧はTCPの仕様(RFC 9293)で定められている。
接続するときの状態
| 状態 | 誰が | 意味 |
|---|---|---|
| CLOSED | 両方 | コネクションがない |
| LISTEN | サーバ | 接続要求(SYN)が来るのを待っている。サーバのプログラムがポートを開いて待ち受けている状態 |
| SYN-SENT | クライアント | SYNを送り、相手からのSYN+ACKを待っている |
| SYN-RECEIVED | サーバ | SYNを受け取ってSYN+ACKを返し、最後のACKを待っている |
| ESTABLISHED | 両方 | コネクションが確立し、データを送受信できる |
サーバがクライアントからのSYNを受け付けるのはLISTENの状態のときである。
切断するときの状態
先にFINを送った側を「能動的に閉じる側」、FINを受け取った側を「受動的に閉じる側」という。
| 状態 | 誰が | 意味 |
|---|---|---|
| FIN-WAIT-1 | 能動的に閉じる側 | FINを送り、そのACKを待っている |
| FIN-WAIT-2 | 能動的に閉じる側 | FINへのACKを受け取り、相手からのFINを待っている |
| CLOSE-WAIT | 受動的に閉じる側 | FINを受け取った。自分のアプリケーションが閉じるのを待っている |
| LAST-ACK | 受動的に閉じる側 | 自分もFINを送り、そのACKを待っている |
| TIME-WAIT | 能動的に閉じる側 | 最後のACKを送り、一定時間待っている |
| CLOSING | 両方 | 双方がほぼ同時にFINを送ったときの状態 |
TIME-WAITで待つ理由
TIME-WAITでは、セグメントがネットワーク上に残りうる最大時間(MSL)の2倍の時間だけ待つ。理由は2つある。
- 最後に送ったACKが失われ、相手がFINを再送してきたときに、ACKを送り直せるようにするため
- 古いコネクションの遅れて届いたセグメントが、同じポート番号を使う新しいコネクションに紛れ込むのを防ぐため
トラブルシューティングでの使い方
netstat や ss コマンドで、コネクションごとの状態を確認できる。
- CLOSE-WAITが大量に残る:アプリケーションが、相手から切断されたコネクションを閉じていない(プログラムの不具合の疑い)
- TIME-WAITが大量に残る:短い接続を大量に繰り返している。待ち時間の間はポートが空かないため、送信元ポートが足りなくなることがある
- SYN-RECEIVEDが大量に残る:SYNフラッド攻撃を受けている可能性がある