home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

日記/2010/09/12/Winsock2, client-sideで shutdown(s, SD_SEND)後にrecv()が0を返す件

日記/2010/09/12/Winsock2, client-sideで shutdown(s, SD_SEND)後にrecv()が0を返す件

日記 / 2010 / 09 / 12 / Winsock2, client-sideで shutdown(s, SD_SEND)後にrecv()が0を返す件
id: 779 所有者: msakamoto-sf    作成日: 2010-09-12 13:37:33
カテゴリ: Windows ネットワーク 

お手伝いの関係でWinsock2を触り始めているが、MSDN掲載の初歩のサンプルコードを打ち込んでみたら妙な挙動になって2時間ほど嵌ってしまった。

  • "MSDN Library" > "Windows Development" > "Networking" > "Network Protocols" > "Windows Sockets 2" > "Using Winsock" > "Getting Started With Winsock" > "Running the Winsock Client and Server Code Sample" > "Complete Winsock Client Code"

このサンプルコードでは send() 後に shutdown(SOCKET, SD_SEND) して「もうこれ以上クライアント側からの送信データはありませんよ」とサーバ側に明示した後、recv()で受信し、closesocket()を呼んでいる。
shutdown()は送信 or 受信 or 両方についてソケットを無効化する。もちろんPOSIXでも定義されているが、あまり見かけることはない。

一旦shutdown()を明示的に呼んでソケットを無効化したのち、recv() or send() で残りのデータ送受信処理を行い、closeするというのはMSDN上では「Graceful Shutdown」と呼ばれているらしい。

  • "MSDN Library" > "Windows Development" > "Networking" > "Network Protocols" > "Windows Sockets 2" > "About Winsock" > "Winsock Programming Considerations" > "Graceful Shutdown, Linger Options, and Socket Closure"

あまり見かけることがないのは、closesokcet()内で暗黙的にgraceful shutdownが呼ばれている為、明示的にshutdown()を呼ばなくても問題ないケースが多い為だろう。

ここからが本題だが、client-sideでの「send() -> shutdown(SD_SEND) -> recv()」で、recv()がいきなり0 = connection closeを返す場合がある。

実験してみたところ、サーバー側が先にFINパケットを送信すると、recv()が0を返す挙動を見つけた。
例えばJavaで作った単純な"echo"サーバーに接続したところ、問題なくrecv()は"echo"サーバーが送信してきたデータを受信出来た。
ところが、送信データを"GET / HTTP.1.0"にしてローカルのApache等に送信してみたところ、かならずrecv()が0を返してしまう。こちらのケースは、Apacheプロセス側が応答パケットの送信に続いてFINパケットまで送ってきている。つまりサーバー側から先に切断フェーズに進む形になる。どうもこのケースにおいては、クライアント側でshutdown(SD_SEND) -> recv() すると0が返されconnection closeとして動作するようだ。

更に、試しにクライアント側でshutdown()の前に適当なwaitを入れてみたところ(getchar())、その場合はrecv()が正常値を返すことを確認出来た。

前述の「graceful shutdown」MSDNでは「クライアント側からの切断」処理については書かれているが、「サーバー側が先に切断フェーズに入った場合」の挙動については書かれていない。

あまりまとまっていないが、shutdown()を明示的に呼び出すgraceful shutdownで期待したとおりの挙動にならない場合は、どちらが先にFINパケットを送り切断フェーズに入ったのかについて注意が必要。


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2010-09-12 13:57:53
md5:09e5e7aa517d58a87400910aeebc5f2b
sha1:8318f6f4f255f837e3cf6b853c293a34331ffa4a
コメント
コメントを投稿するにはログインして下さい。