Shammer's Philosophy

My private adversaria

TCP Socket 状態遷移

詳しく書かれたサイトを見つけたのでメモ。

 第15回 信頼性のある通信を実現するTCPプロトコル(2) (3/3):基礎から学ぶWindowsネットワーク - @IT
 第16回 信頼性のある通信を実現するTCPプロトコル(3) (3/4):基礎から学ぶWindowsネットワーク - @IT

詳細はリンク先を読むとして、要点は以下だろうか。

  • Open/Close ともにアクティブ・パッシブがある
  • アクティブは自分から行動を起こす感じ(自分から SYN や FIN を投げる)
  • パッシブは相手からの要求に応える感じ(相手からの SYN や FIN に応じる)

これまで、勝手にオープンした側からクローズしないと変な動作になるのだと思っていたが、そうでもないようだ。いや、Windows のパケットだと不要と思われる RST が飛んでいるように見えたりして、その理由を勝手に自分からオープンしたのに相手からクローズを受けたからだと思ったりして・・・いや、やっぱりよくわかっていないかも。

とりあえず、Active Open の場合は以下のようになる。

  1. SYN_SENT
  2. ESTABLISHED

Passive Open は以下のようになる。

  1. LISTEN
  2. SYN_RECEIVED
  3. ESTABLISHED

まあ、SYN_SENT も SYN_RECEIVED も実際には一瞬で、netstat とかでもほとんど見ることないだろう。

Active Close は以下のようになる。

  1. ESTABLISHED
  2. FIN_WAIT_1
  3. FIN_WAIT_2 or CLOSING
  4. TIME_WAIT
  5. CLOSED(消える)

FIN_WAIT_2 になるか、CLOSING になるかは、FIN のみを受け取るか、FIN+ACK を受け取るかで異なる。

Passive Close は以下のようになる。

  1. ESTABLISHED
  2. CLOSE_WAIT
  3. LAST_ACK
  4. CLOSED(消える)

アプリの実装で、FIN を受け取った Socket を close() させていないと FD 枯渇して Too many open files になるという問題を散々やってきた。そのときの状態が CLOSE_WAIT だ。なので、CLOSE_WAIT は悪いものだと呪文のように覚えている。アプリのレイヤからは、オープン、データ送受信、クローズしかできないし、アプリレベルでは送受信するデータの加工の方がそもそも重要だから、この辺はよく理解できていなかった。こういうサイトがあると助かる。