大きな画面での利用をおすすめします — アニメーションと操作がより快適になります。
入力

TCP 接続の終了

TCP は二つの送信方向を独立して閉じる。本課は通常の FIN、ACK、FIN、ACK の四段を示す。能動側は FIN_WAIT_1→FIN_WAIT_2→TIME_WAIT→CLOSED、受動側は CLOSE_WAIT→LAST_ACK→CLOSED と進む。

片方が送信終了を伝えても、他方は確認した後まだ送ることがある。自身も終えたら FIN を送り、能動側は最後に 2·MSL の TIME_WAIT を保持する。FIN の再送へ応答し、古いセグメントの期限切れも待つためだ。

仕組み

クライアントが能動的に送信を閉じ、FIN seq=u を送る。サーバーは ACK ack=u+1 を先に返し、自分の方向は続けられる。これが半閉鎖だ。その後 FIN seq=w, ack=u+1 を送り、クライアントが ack=w+1 で確認する。

FIN は SYN と同様、ペイロードなしでも一シーケンス番号を消費する。ACK は次を期待するので +1。本課は実際の 32 ビット番号の代わりに u、w を使う。

中間 ACK と二つ目の FIN は同時に準備できるとは限らず、ここでは四段になる。受動側もすぐ閉じられれば組み合わせられるので、毎回独立四パケットと決め付けない。受信を保つ半閉鎖には実 API で shutdown などを使い、close の資源挙動は環境に従う。

ステップ実行

Normal close は 13 ステップ。

  1. 両側 ESTABLISHED。クライアントのアプリが終了を開始する。
  2. 第 1 段 FIN seq=u を送り、FIN_WAIT_1 へ。
  3. サーバーは受けてクライアントの送信終了を知り、CLOSE_WAIT へ。
  4. 第 2 段 ACK ack=u+1 を送る。
  5. クライアントは受け、FIN_WAIT_2 へ。自分の送信方向が確認済みで閉じる。
  6. 半閉鎖の窓。サーバーはまだデータを持ち得て、送信済み ACK と未送信 FIN を分ける。
  7. サーバーは送信を終え、第 3 段 FIN seq=w, ack=u+1 を送り LAST_ACK へ。
  8. クライアントは FIN を受け、TIME_WAIT へ。
  9. 第 4 段 ACK ack=w+1 を送る。
  10. サーバーは受けて CLOSED。この例はサーバーが先に終わる。
  11. クライアントは 2·MSL 待ち、再送 FIN の確認と古い重複段の期限切れに備える。
  12. 期限で CLOSED へ。
  13. 両階段が CLOSED となり、通常終了を終える。

移動カードと状態ラベルを生命線に示し、古いラベルを薄くする。転送と TIME_WAIT は遅く見せ、番号と状態を照合できる。

TIME_WAIT の役割

純 ACK はそれ自体を ACK されず、最後の確認も同じだ。クライアントは到着を確定できない。

Lost final ACK は ack=w+1 を落とす。サーバーは LAST_ACK に残り、再送期限で FIN seq=w を出す。TIME_WAIT のクライアントは ACK ack=w+1 を再送し、2·MSL を再開始する。今度はサーバーが閉じ、クライアントも新期限後に閉じる。

最後の ACK 直後に状態を捨てれば、再送 FIN が接続のない場所へ届き、正常な再確認でなく RST になる可能性がある。2·MSL は同じ接続識別を再利用する前に旧段を消す役割もあるが、任意の遅延・喪失への絶対保証ではない。全状態と時間規則は RFC 9293を参照。

境界ケース

  • 最後の ACK 喪失では LAST_ACK が FIN を再送し、TIME_WAIT が再確認して時計を再始動する。
  • 同時終了は双方が相手を見る前に FIN を送り、FIN_WAIT_1→CLOSING→TIME_WAIT で両方待ち得る。ここでは未展開。
  • 相手が FIN を出さなければ FIN_WAIT_2 に残り得る。アプリがもう持たない接続などに掃除期限を設ける実装もあり、全半閉鎖に同じ期限を仮定しない。
  • RST による中止はこの正常 FIN 経路とは異なり、未配達データを捨て得る。

よくある間違い

  • 三段で済むと決め付け、受動側の残る送信を無視する。逆に ACK と FIN が絶対結合できないとも言えない。
  • 両側が同時に CLOSED と思う。既定はサーバーが先、クライアントは TIME_WAIT。
  • 待機を無駄とする。最終確認の再送と旧段分離を支え、大量に能動終了するサーバー側にもたまる。
  • TIME_WAIT をクライアント固定、または必ず片側だけとする。通常例は能動側、同時終了なら両端だ。
  • FIN の番号消費を忘れる。確認は u+1 と w+1。

モデルの範囲

記号番号を使い、データ転送を挟まず、再送と待機を短い説明動作にする。通常の能動・受動終了と最終 ACK の一回喪失だけで、全状態組、資源回収、スタック最適化を再現しない。