性格悪い人が優勝

MFC VC++6.0で、ソケット通信を勉強しています。

サーバー側を
http://athomejp.com/goldfish/mfc/socket/socketse …
を参考に「ソケットから何かを受信する」ところの
配列サイズとwhileの条件を

char szBuf[1024];
while( nret != 0 )

に変更しました。

クライアントからは64バイトの送信をしているのですが、
サーバでReceiveしたサイズが16バイトで、whileを抜けてしまいます。
何が原因でしょうか、ご教示ください。
お願いいたします。

A 回答 (4件)

>サーバでReceiveしたサイズが16バイトで、whileを抜けてしまいます。


>何が原因でしょうか、ご教示ください。

質問ページの下の方に
------------------------
また、一回のSendやReceiveでは、データが送受信できるとは限らないため、ソケットの送受信は、必ず、戻り値をチェックすること。
------------------------
と書いてあります。

ちょっと判りにくいですが、これは
------------------------
また、一回のSendやReceiveでは、すべてのデータが1回で送受信できるとは限らないため、ソケットの送受信は、必ず、戻り値をチェックすること。
また、送信した直後、送信バッファが一杯だと、2回目以降の送信バイト数が0になる事がある。
同様に、受信した直後、受信バッファにまだ続きのデータが何も溜まってないと、2回目以降の受信バイト数が0になる事がある。
------------------------
と言う意味です。

また、受信の場合「運が悪いと、ソケットが繋がった直後の最初の受信で、受信バッファがまだ空っぽで、0バイトしか読まない」なんて事も起きます。

質問者さんの場合では、送り側で64バイト送信しても、受け側で「何か来た!受け取れ!」と思って受け取っても「まだ64バイト全部来てなくて、頭の16バイトしか受け取れず、続きを受け取ろうと2回目の受信をしてみたらまだ続きが全然来てなくて何も受け取れず、nretが0になってループを抜けちゃった」って事が起きた訳です。

送信側で64バイト送っても、受信側は
・1回目で16バイト受け取る
・2回目で0バイト受け取る
・3回目で0バイト受け取る
・4回目で8バイト受け取る
・5回目で0バイト受け取る
・6回目で0バイト受け取る
・7回目で8バイト受け取る
・8回目で0バイト受け取る
・9回目で0バイト受け取る
(以下略)
って事が起きちゃう訳です。

ループ条件を
while( nret != 0 )
にしてしまうと、2回目の「続きがまだ全然来てなくて0バイト読んだ」って状態でループを抜けてしまうのです。

この問題は「CSocketが、ノンブロッキング、ブロッキング(ノンバッファリング、バッファリング)をかなり無茶な方法で実装している」のが原因で発生します。
    • good
    • 1

訂正。



質問ページの下の方に

質問文で参考にしたページの下の方に
の誤りです。
    • good
    • 0

http://www.kt.rim.or.jp/~ksk/wskfaq-ja/articles/ …

CSocketは色々と問題があるみたいですね。
なんらかの原因でnretの値として0が返されている可能性があります。
while( nLen != sizeof( szBuf))
の場合は
nLen += nret;
でnLenがクライアント側の送出データサイズに到達するまではループから抜けることができないので、すべてのデータが受信できているのでしょう。
    • good
    • 0

>char szBuf[1024];


>while( nret != 0 )
>に変更しました。
>クライアントからは64バイトの送信をしているのですが、
>サーバでReceiveしたサイズが16バイトで、whileを抜けてしまいます。
>何が原因でしょうか、ご教示ください。

当然、nretが0ではないからループから抜けたのでしょう。
送信側のsend()で1024バイトを1度で送信しても、受信側のreceive()1回で1024バイト受信できるとは限りません。

16バイト受信した後で、再度receive()を実行すると残りの48バイトが一度でとれるかも知れません。
# 勿論、そんな保証はないので16バイトずつ繰り返しになるかも知れませんし、もっと分断して受信するかも知れません。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!