最近はまったTCPの挙動

時折思い出したように技術系になる本サイトですが。

まあ、サーバ側ではちゃんとclose()してるように見えるのに、なぜかクライアントはRSTを受け取っちゃうという話。読んでる側も書いてる側も直接ソケットをいじってるなら分かりやすいんだけど、アプリケーションレベルでいろんなプロトコルを扱うために、両方とも盛大にデコレーションされているわけで。そうなってくると、だんだんよくわかんなくなってくる。だいたい初見のコードだし。

結局はコレでした。

4.2.2.13 Closing a Connection: RFC-793 Section 3.5
...
A host MAY implement a "half-duplex" TCP close sequence, so
that an application that has called CLOSE cannot continue to
read data from the connection. If such a host issues a
CLOSE call while received data is still pending in TCP, or
if new data is received after CLOSE is called, its TCP
SHOULD send a RST to show that data was lost.
...

http://www.ietf.org/rfc/rfc1122.txt

途中の層でプロトコル解釈を間違っていて、ごくまれにsocket input bufferにデータを残しちゃうという。わかってしまえば単純なんだけど、誰が読んで誰が書いて誰がクローズするのかといったところで責任が分散したり盛大に非同期になってきたりすると、倍率ドンさらに倍で難しくなります。この問題は、タイミングによって起きたり起きなかったりしたので、そもそもそういう問題であるというところまで特定するのが一苦労、そんでもって、この挙動がまたTCP/IP Illustratedとかに書いてないのでもう一苦労。つうことで、RFCはちゃんと読みましょうという話でした。USのWikipediaもわりとよく書けてるかも。

http://en.wikipedia.org/wiki/Transmission_Control_Protocol