質問: android端末のアプリ使用でTCP切断時、正常であれば『サーバ⇒端末』にFINが投げられた後、即『端末⇒サーバ』へFINを返しています。 ただ時たま、『サーバ⇒端末』にFINが投げられた後、『端末⇒サーバ』へFINを返す際に120sほどかることがあります。 こちら、遅れる原因としてどういったものが考えられますでしょうか。 OSの問題でしょうか。 ※端末アプリにはHTTPリクエスト時の共通処理として、ソケットのクローズ処理があります
回答: AndroidOSに搭載されているTCPプロトコルのソフトウェアのバグの可能性も否定出来ませんが TCPのクローズ処理のシーケンスとして以下のような流れになります。 サーバ:FIN(これをもってサーバからデータ送信しない) -> ACK応答(OKわかった。でもクライアントはまだ送信するかもしれないよ) クライアント:FIN(これをもってクライアントからデータ送信しない) -> ACK応答(OKわかった) サーバ・クライアント:双方FINを認識したのでじゃあクローズとしよう。 つまり、『サーバ -> 端末』でのFIN時点ではTCP切断は成立していません。(shutdown状態) また、サーバ側はsend()する事は出来ませんが、shutdown(読込)していなければrecv()は可能)ですし クライアント側はsend()もrecv()もする事が出来ます。但し、使用しているソケットに対して クライアントがrecv()をした時、TCPプロトコル側に"**受信データがない**"と戻り値として「0」が返ります。(もうサーバから送られる可能性が無いので) なのでクライアントからのFINが遅れる原因として考えられる可能性は、 クライアント側がclose()またはshutdown(書込)を実行してサーバ側にFIN送信をしていないのではないでしょうか。 具体的にはクライアント側がまだ受信処理をしている、とか送信処理をしているとか。(まだ仕事をしている) またはクライアント側のアプリケーションの問題で適切にclose()を発行していないのかもしれませんね。 話を聞く限り、120秒も掛かっているのでTCPプロトコルかアプリケーションの何らかの問題の可能性が高いかもしれません。 設定にもよりますが120秒という切りの良い時間ですし、サーバ側が実行したclose()がタイムアウトして切断が成立しているのかもしれません。 パケットキャプチャ見ないとわかりませんが、サーバがclose()でタイムアウト(TIME-WAIT2 -> CLOSED)になった後にクライアントからデータ送信が来た場合RSTを返すはずなので そういう動きになっていればclose()のタイムアウトで強制切断になっている可能性が高いと思います。