- ベストアンサー
recv関数の戻り値について
おせわになります。 socket関数(WinSock2)のrecv関数のことで質問なのですが、 第4引数にMSG_PEEKを指定したときと、指定しない時(=0) の戻り値が、明らかに違うのです。 実際は、20000バイトを送信し、受信側でrecvすると、 MSG_PEEKを指定すると、8760が返り、 MSG_PEEKを指定しない(=0)と、20000が返ります。 (もっと試して、200000と10倍にしても一回で受信しました。) recvが一度に受信できる容量のテストをしていたときに発見したのですが、こういうものなのでしょうか? 以上、よろしくおねがいします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
>『もしかしたら、オプションで指定した容量内にもかかわらず、 >recvで受信するときに2回以上に分けて受信する必要性がでてくることも可能性としてあるのだろうか?』 >というテストです。 可能性がある。 としてプログラムしておいたほうが良いかと。 MSG_PEEK自体アテにするつもりがないのでrecv()の戻り値使って処理してます。 送信側が20000バイトを1回のsend()で送っても、 受信側が1回のrecv()で20000バイト受信できる保証はないワケですし。 http://www.kt.rim.or.jp/~ksk/wskfaq-ja/newbie.html#peeking とか。 # 使ったプロトコルがせいぜいPOP3程度だし。 # それでもrecv()の戻り値を正しく扱わなくて不具合出したことがある。
その他の回答 (2)
- aris-wiz
- ベストアンサー率38% (96/252)
既にアドバイスがついていますが一応 >【recv関数において、MSG_PEEKを指定したときとしないときで >受信するバイト数が違うのはなぜか?】 No2さんの参照先。。。 今回のサイズの違いはバグということでしょうかね。。。; >『もしかしたら、オプションで指定した容量内にもかかわらず、 >recvで受信するときに2回以上に分けて受信する必要性が >あるのだろうか?』 当然考えられます。 これらは通信の帯域によっても変わってくるものですし、 設定した値は最大の許容量であって、OSが、 許容しているサイズを全て使い切る保障が無い以上、 指定したサイズ未満の受信の場合を考慮しなければなりません。 >recvはブロッキングでなく使えってことですよねー。 サーバ関係のプログラムだと、マルチスレッドでワーカと、 ノンブロッキングというのがかなりデフォルトな感じな 気がするのですが、私だけですかね:-p
お礼
ありがとうございます。 まぁもちろんマルチスレッドにはしてますし、 サーバならノンブッキングにしてます。
- aris-wiz
- ベストアンサー率38% (96/252)
recvの関数リファレンスはご覧になりましたか? また、MSG_PEEKの意味はお分かりでしょうか? recvが返す値は、 実際に読み込んだバイト数、または、 関数失敗時SOCKET_ERROR(-1)、または 接続終了時の0 上記3つの値を返します。 MSG_PEEKは受信キューから読み込んだデータを 取り除かないことを意味します。 どのようなプログラムを書いて、どのような環境で テストしているのか判りませんが、こういうものなのか?と いわれても、実際の環境やプログラムのコードを提示しない限り、 それらに答えることは難しいでしょう。 >recvが一度に受信できる容量のテスト そもそも、何故このテストをする必要があるのか不明ですが、 recvが一度に受信できるサイズについては、 ソケットオプションで変更することが可能ですし、 これらのサイズはOSが決めた最大値を超えることは無く、 また、実際にはどのような数値が帰ってきてもおかしくないので、 あまり意味は無いと思うのですが。。。 これらのサイズに依存するプログラムを書くよりも どのようなサイズが帰ってきても、適切に処理するように すべきだと思います。
補足
回答どうもありがとうございます。 recvの関数リファレンスはもちろん見ています。 質問の意図は、 【recv関数において、MSG_PEEKを指定したときとしないときで受信するバイト数が違うのはなぜか?】 ということです。 上記の疑問に対して、『こういうものなのか?』という記述をしました。 このテストはもう少し正確に言うと、 【ソケットオプションで変更した値が本当に信用できるのか?】 という意味です。 『もしかしたら、オプションで指定した容量内にもかかわらず、 recvで受信するときに2回以上に分けて受信する必要性がでてくることも可能性としてあるのだろうか?』 というテストです。 以上、よろしくおねがいします。
お礼
ありがとうございました。 そうすると、recvはブロッキングでなく使えってことですよねー。 戻り値をとろうとして、終了してたらブロキングしちゃいますからねー。