こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

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()に処理が行かなければ反応していない、としています。

これはどうしてでしょうか?

投稿日時 - 2013-06-15 21:04:43

QNo.8135538

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(7)

あとはもう、現象が発生する最低限のソースを、とぐらいしか。

投稿日時 - 2013-06-17 19:34:51

補足

最低限のソースを作ってみました。
DXライブラリを用いているのですがどこかにアップロードしたのを落としてもらうようにする形でいいのでしょうか?
その場合、DXライブラリの関数を使用しているためどのような処理を行っているかをコメントに書くためにまた少しお時間をいただきたいです。

また、最低限のソースと同じような形でコンソールプログラムに書き換えたところ、思ったように動きました。
もしかしたらDXライブラリが原因の可能性も・・・・?

投稿日時 - 2013-06-18 21:15:26

> プログラム上ではif文の中に入ってsend()の処理が
> 行われているのにそんなことあるんでしょうか?

Visual Studioだと、変更部分のみビルドとかエディットコンティニューとか使ってたりすると、デバッグ実行で実行位置がおかしくなったり、動作がおかしくなったりということが稀に起こるかと。まあ、リビルドすれば直りますが。


ソースが問題ないのにうまくいかなかった経験としては、セキュリティソフトのファイアウォールに引っかかってたということがありました。その時はその機能を一時的にOFFにしたらうまくいきました。
ただ、今までのところ、接続できないということはあっても、sendが途中からうまくいかないいうことはなかったとは思いますが。

投稿日時 - 2013-06-16 21:55:23

補足

VC++2010にも問題ないようですし、ファイアーウォールにも問題ありません。

どうしたものでしょうか

投稿日時 - 2013-06-17 13:34:19

「send() に成功している」は、ちゃんと戻り値が送信バイト数になっていたことを確認してのことでしょうか?

また、if を使わなければ受信できるということは、コードを

send( Sock, "hello", 5, 0 );
send( Sock, "hello", 5, 0 );

と単に連続で送るように書き換えても、受信側はちゃんと2回分のデータを受信できている、ということなのでしょうか?

これで受信できていないなら受信側コードが何かおかしいのでしょうし、受信できているなら if の条件が間違っているとしか思えないのですが。

投稿日時 - 2013-06-16 20:57:48

補足

受信できています。

>if の条件が間違っているとしか思えない
プログラム上ではif文の中に入ってsend()の処理が行われているのにそんなことあるんでしょうか?

投稿日時 - 2013-06-16 21:14:57

ANo.4

>手動である分どんなに早くても1秒程度はかかりますし、少なくとも1:1で反応するのではないでしょうか?

なぜ「~数秒程度かかるのだから送信されているはず」という仮定をされてるのでしょうか?
バッファリングされていて実際には送信されていない(その次のsendと一緒に送られる)という事もありえるんですが。

投稿日時 - 2013-06-16 19:39:45

補足

そんなことがあるんですね。

そこで、
if文内とif文外両方共にsend()を書き、送信内容を中と外で区別つくように書き換えて(HelloとHELLOのように)
ループさせたところ、

外のHELLOは何回も受信されますが中のHelloは受信されませんので、バッファリング?はなさそうです。

投稿日時 - 2013-06-16 21:19:52

ANo.3

>ここでいう、サーバーが反応するとは、select()を用いてブロッキングが解除されてrecv()に処理が回れば反応した、recv()に処理が行かなければ反応していない、としています。

TCPはsendの回数とrecvの回数が一致するとは限らないので、それで判断してもダメです。

投稿日時 - 2013-06-16 18:27:27

補足

VC++2010でブレイクポイントをsend()のところとすぐ次の処理の二か所にそれぞれ作り、
サーバー側にはrecv()後にブレイクポイントを作り、
send()を一回通り過ぎたらrecv()に反応があるか確認し、とやっているので、手動である分どんなに早くても1秒程度はかかりますし、少なくとも1:1で反応するのではないでしょうか?

投稿日時 - 2013-06-16 18:54:31

単に2回sendされたデータを1回のrecvでまとめて受け取ってるだけではないでしょうか。
受信側で実際に受け取ったデータサイズを確認してみましたか?

投稿日時 - 2013-06-16 17:35:57

補足

少なくともVC++2010上で確認する限りは
バイト数も受信内容も1個分しか受信していません。

投稿日時 - 2013-06-16 18:49:46

ANo.1

Wr5

>if文の外のsend()にはサーバーが反応するのですが、if文内のsend()はsend()が行われているのが確認されるのにもかかわらずサーバー側が一切反応しません。

Wiresharkなどで「間違い無く送信されている」というコトを確認していますか?

条件とか不明ですから掲示されている内容だけでは、「実は実行されていない」という可能性も否定できません。
# あるいはsend()に失敗しているかも知れませんし。

まぁついでに……滅多にないとは思いますが、send()してもすぐに送信されない。ということもあるかも知れません。
送信バッファに入ればsend()は戻って来ますしね。

投稿日時 - 2013-06-16 13:38:28

補足

>Wiresharkなどで「間違い無く送信されている」というコトを確認していますか?
いえ、VC++2010のデバックモードで処理が通っているか(返り値はいくつかも含め)で判断していました。

printf()などをif文に記述してみるという確認方法を取っても確実にif分の中に入っています。

そのため、if文外だと6回中6回成功し、if文内だと6回中6回失敗する原因が全く思いつかないのです。
if文内だと、すぐに送信されないとか、send()に失敗するとかありませんよね?

wiresharkの使用結果はお礼の方に書かせていただきます

投稿日時 - 2013-06-16 14:18:43

お礼

127.0.0.1を使っているのでWireSharkでは無理でした
やる方法はあるようですが、それに沿ってやってみたものの、出来ません。(コマンドプロンプトからのping送信がキャプチャされない)

投稿日時 - 2013-06-16 14:53:47

あなたにオススメの質問