いろんなものはつながっている

Graceful Shutdown

ソケットのクローズの動作の説明を調べていたところ、ここの説明がわかりやすかった。

お互い、FINとACKを送りあうわけだが、最初にクローズした(アクティブクローズ)側は、最後に送ったACKが相手に届いたか確認しようがないので、すでにネットワーク上にある電文が消えるまで、一定時間、再送待機(TIME_WAIT)状態になる。TIME_WAIT状態の間はそのポートは使用できない。

シーケンス図はこちらを参照

ちなみに、クローズ後にソケットが電文をうけとった場合、ACKではなくRSTを返す。

SO_LINGERオプションで時間0をセットすると、TIME_WAIT状態にならずにいきなりクローズする。
ちなみに、LINGERはとどまるという意味。英単語も“こんな感じでアニメーションで教えてくれるとかなりわかりやすい。

また、シャットダウン→クローズの手順で、Graceful Shutdownというものがあることを知った。

これは、クライアント側でまず、shutdown(SEND)で送信を禁止し、サーバ側にFINを送信する。
FINを受け取ったサーバ側は、もうクライアント側からデータがこないことをこないことを知るので、残っている応答データをクライアントに送信する。
クライアント側はサーバから送られてきたデータをRECEIVEする。
サーバ側は、残っている応答データをクライアントに送信し終わったらshutdoown(SEND)を実行し、サーバ側にFINを送る。
クライント側は、FINを受け取るのでソケットをクローズする。

いきなり、closeksocketしても、内部でgraceful shutdownが実施される。ただ、まれに、closesocketしたとにクライアント側でデータを受信した際に、受信イベントが発生してしまうことがあるので、明示的にgraceful shutdownをしたほうがよい。

//ソケットシャットダウン
socket.Shutdown(SocketShuddown.Send);
//受信バッファ刈り取り
byte[] buff = new byte[1024];
while(true)
{
	int revSize = socket.Receive(buff);
	//受信が0になったらループを抜ける
	//受信したデータは捨てる
	if(revSize = 0)
	{
		break;
	}
}

//ソケット切断
socket.closesocket.

関連記事

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

スポンサード リンク

カテゴリー

スポンサード リンク