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 の場合は以下のようになる。
- SYN_SENT
- ESTABLISHED
Passive Open は以下のようになる。
- LISTEN
- SYN_RECEIVED
- ESTABLISHED
まあ、SYN_SENT も SYN_RECEIVED も実際には一瞬で、netstat とかでもほとんど見ることないだろう。
Active Close は以下のようになる。
- ESTABLISHED
- FIN_WAIT_1
- FIN_WAIT_2 or CLOSING
- TIME_WAIT
- CLOSED(消える)
FIN_WAIT_2 になるか、CLOSING になるかは、FIN のみを受け取るか、FIN+ACK を受け取るかで異なる。
Passive Close は以下のようになる。
- ESTABLISHED
- CLOSE_WAIT
- LAST_ACK
- CLOSED(消える)
アプリの実装で、FIN を受け取った Socket を close() させていないと FD 枯渇して Too many open files になるという問題を散々やってきた。そのときの状態が CLOSE_WAIT だ。なので、CLOSE_WAIT は悪いものだと呪文のように覚えている。アプリのレイヤからは、オープン、データ送受信、クローズしかできないし、アプリレベルでは送受信するデータの加工の方がそもそも重要だから、この辺はよく理解できていなかった。こういうサイトがあると助かる。