- 締切済み
if文の中ではwinsockのsendが出来ない?
struct C_Commu { ----WSADATA wsadata; ----SOCKET Sock; ----sockaddr_in Addr; public: ----void Init(); ----void Send(); } というクラスがあったとします。 Init()ではソケットの生成だとかWinsockを使った通信で必要な設定を行っています。(TCPとする) void C_Commu::Send() { ----send( Sock, "hello", 5, 0 ); ----if(何らかの条件) ----{ --------send( Sock, "hello", 5, 0 ); ----} } このような関数の場合に、if文の外のsend()をコメントアウトしたりコメントにしたりして動作を確認してみたところ if文の外のsend()にはサーバーが反応するのですが、if文内のsend()はsend()が行われているのが確認されるのにもかかわらずサーバー側が一切反応しません。 ここでいう、サーバーが反応するとは、select()を用いてブロッキングが解除されてrecv()に処理が回れば反応した、recv()に処理が行かなければ反応していない、としています。 これはどうしてでしょうか?
- みんなの回答 (7)
- 専門家の回答
みんなの回答
- fresh_homepie
- ベストアンサー率64% (24/37)
あとはもう、現象が発生する最低限のソースを、とぐらいしか。
- fresh_homepie
- ベストアンサー率64% (24/37)
> プログラム上ではif文の中に入ってsend()の処理が > 行われているのにそんなことあるんでしょうか? Visual Studioだと、変更部分のみビルドとかエディットコンティニューとか使ってたりすると、デバッグ実行で実行位置がおかしくなったり、動作がおかしくなったりということが稀に起こるかと。まあ、リビルドすれば直りますが。 ソースが問題ないのにうまくいかなかった経験としては、セキュリティソフトのファイアウォールに引っかかってたということがありました。その時はその機能を一時的にOFFにしたらうまくいきました。 ただ、今までのところ、接続できないということはあっても、sendが途中からうまくいかないいうことはなかったとは思いますが。
補足
VC++2010にも問題ないようですし、ファイアーウォールにも問題ありません。 どうしたものでしょうか
- fresh_homepie
- ベストアンサー率64% (24/37)
「send() に成功している」は、ちゃんと戻り値が送信バイト数になっていたことを確認してのことでしょうか? また、if を使わなければ受信できるということは、コードを send( Sock, "hello", 5, 0 ); send( Sock, "hello", 5, 0 ); と単に連続で送るように書き換えても、受信側はちゃんと2回分のデータを受信できている、ということなのでしょうか? これで受信できていないなら受信側コードが何かおかしいのでしょうし、受信できているなら if の条件が間違っているとしか思えないのですが。
補足
受信できています。 >if の条件が間違っているとしか思えない プログラム上ではif文の中に入ってsend()の処理が行われているのにそんなことあるんでしょうか?
- wormhole
- ベストアンサー率28% (1626/5665)
>手動である分どんなに早くても1秒程度はかかりますし、少なくとも1:1で反応するのではないでしょうか? なぜ「~数秒程度かかるのだから送信されているはず」という仮定をされてるのでしょうか? バッファリングされていて実際には送信されていない(その次のsendと一緒に送られる)という事もありえるんですが。
補足
そんなことがあるんですね。 そこで、 if文内とif文外両方共にsend()を書き、送信内容を中と外で区別つくように書き換えて(HelloとHELLOのように) ループさせたところ、 外のHELLOは何回も受信されますが中のHelloは受信されませんので、バッファリング?はなさそうです。
- wormhole
- ベストアンサー率28% (1626/5665)
>ここでいう、サーバーが反応するとは、select()を用いてブロッキングが解除されてrecv()に処理が回れば反応した、recv()に処理が行かなければ反応していない、としています。 TCPはsendの回数とrecvの回数が一致するとは限らないので、それで判断してもダメです。
補足
VC++2010でブレイクポイントをsend()のところとすぐ次の処理の二か所にそれぞれ作り、 サーバー側にはrecv()後にブレイクポイントを作り、 send()を一回通り過ぎたらrecv()に反応があるか確認し、とやっているので、手動である分どんなに早くても1秒程度はかかりますし、少なくとも1:1で反応するのではないでしょうか?
- fresh_homepie
- ベストアンサー率64% (24/37)
単に2回sendされたデータを1回のrecvでまとめて受け取ってるだけではないでしょうか。 受信側で実際に受け取ったデータサイズを確認してみましたか?
補足
少なくともVC++2010上で確認する限りは バイト数も受信内容も1個分しか受信していません。
- Wr5
- ベストアンサー率53% (2173/4061)
>if文の外のsend()にはサーバーが反応するのですが、if文内のsend()はsend()が行われているのが確認されるのにもかかわらずサーバー側が一切反応しません。 Wiresharkなどで「間違い無く送信されている」というコトを確認していますか? 条件とか不明ですから掲示されている内容だけでは、「実は実行されていない」という可能性も否定できません。 # あるいはsend()に失敗しているかも知れませんし。 まぁついでに……滅多にないとは思いますが、send()してもすぐに送信されない。ということもあるかも知れません。 送信バッファに入ればsend()は戻って来ますしね。
お礼
127.0.0.1を使っているのでWireSharkでは無理でした やる方法はあるようですが、それに沿ってやってみたものの、出来ません。(コマンドプロンプトからのping送信がキャプチャされない)
補足
>Wiresharkなどで「間違い無く送信されている」というコトを確認していますか? いえ、VC++2010のデバックモードで処理が通っているか(返り値はいくつかも含め)で判断していました。 printf()などをif文に記述してみるという確認方法を取っても確実にif分の中に入っています。 そのため、if文外だと6回中6回成功し、if文内だと6回中6回失敗する原因が全く思いつかないのです。 if文内だと、すぐに送信されないとか、send()に失敗するとかありませんよね? wiresharkの使用結果はお礼の方に書かせていただきます
補足
最低限のソースを作ってみました。 DXライブラリを用いているのですがどこかにアップロードしたのを落としてもらうようにする形でいいのでしょうか? その場合、DXライブラリの関数を使用しているためどのような処理を行っているかをコメントに書くためにまた少しお時間をいただきたいです。 また、最低限のソースと同じような形でコンソールプログラムに書き換えたところ、思ったように動きました。 もしかしたらDXライブラリが原因の可能性も・・・・?