• 締切済み

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

みんなの回答

回答No.7

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

Null0lluN
質問者

補足

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

回答No.6

> プログラム上ではif文の中に入ってsend()の処理が > 行われているのにそんなことあるんでしょうか? Visual Studioだと、変更部分のみビルドとかエディットコンティニューとか使ってたりすると、デバッグ実行で実行位置がおかしくなったり、動作がおかしくなったりということが稀に起こるかと。まあ、リビルドすれば直りますが。 ソースが問題ないのにうまくいかなかった経験としては、セキュリティソフトのファイアウォールに引っかかってたということがありました。その時はその機能を一時的にOFFにしたらうまくいきました。 ただ、今までのところ、接続できないということはあっても、sendが途中からうまくいかないいうことはなかったとは思いますが。

Null0lluN
質問者

補足

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

回答No.5

「send() に成功している」は、ちゃんと戻り値が送信バイト数になっていたことを確認してのことでしょうか? また、if を使わなければ受信できるということは、コードを send( Sock, "hello", 5, 0 ); send( Sock, "hello", 5, 0 ); と単に連続で送るように書き換えても、受信側はちゃんと2回分のデータを受信できている、ということなのでしょうか? これで受信できていないなら受信側コードが何かおかしいのでしょうし、受信できているなら if の条件が間違っているとしか思えないのですが。

Null0lluN
質問者

補足

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

  • wormhole
  • ベストアンサー率28% (1622/5658)
回答No.4

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

Null0lluN
質問者

補足

そんなことがあるんですね。 そこで、 if文内とif文外両方共にsend()を書き、送信内容を中と外で区別つくように書き換えて(HelloとHELLOのように) ループさせたところ、 外のHELLOは何回も受信されますが中のHelloは受信されませんので、バッファリング?はなさそうです。

  • wormhole
  • ベストアンサー率28% (1622/5658)
回答No.3

>ここでいう、サーバーが反応するとは、select()を用いてブロッキングが解除されてrecv()に処理が回れば反応した、recv()に処理が行かなければ反応していない、としています。 TCPはsendの回数とrecvの回数が一致するとは限らないので、それで判断してもダメです。

Null0lluN
質問者

補足

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

回答No.2

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

Null0lluN
質問者

補足

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

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

>if文の外のsend()にはサーバーが反応するのですが、if文内のsend()はsend()が行われているのが確認されるのにもかかわらずサーバー側が一切反応しません。 Wiresharkなどで「間違い無く送信されている」というコトを確認していますか? 条件とか不明ですから掲示されている内容だけでは、「実は実行されていない」という可能性も否定できません。 # あるいはsend()に失敗しているかも知れませんし。 まぁついでに……滅多にないとは思いますが、send()してもすぐに送信されない。ということもあるかも知れません。 送信バッファに入ればsend()は戻って来ますしね。

Null0lluN
質問者

お礼

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

Null0lluN
質問者

補足

>Wiresharkなどで「間違い無く送信されている」というコトを確認していますか? いえ、VC++2010のデバックモードで処理が通っているか(返り値はいくつかも含め)で判断していました。 printf()などをif文に記述してみるという確認方法を取っても確実にif分の中に入っています。 そのため、if文外だと6回中6回成功し、if文内だと6回中6回失敗する原因が全く思いつかないのです。 if文内だと、すぐに送信されないとか、send()に失敗するとかありませんよね? wiresharkの使用結果はお礼の方に書かせていただきます

関連するQ&A

  • 延々と受信し続けるwinsockのrecv

    以下のサーバープログラムを用いて、 (acceptしたらスレッド作成し、作成が終ったということをクライアントに知らせるために文字列送信後受信待機している) #include <winsock2.h> #include <vector> #include <process.h> #include <algorithm> char *Ver = "0.00"; using namespace std; unsigned __stdcall Patch( void *Sock ); int main() { ----WSADATA wsaData; --------WSAStartup( MAKEWORD(2,0), &wsaData ); ----SOCKET RecvSock = socket( AF_INET, SOCK_STREAM, 0 ); ----SOCKET SendSockBuf; ----vector<SOCKET> SendSock; ----fd_set ConnectFds, SubConnectFds; ----struct sockaddr_in Recv, Send; ----int len = sizeof(Send); ----Recv.sin_family = AF_INET; ----Recv.sin_port = htons(55555); ----Recv.sin_addr.S_un.S_addr = INADDR_ANY; --------bind(RecvSock, (struct sockaddr *)&Recv, sizeof(Recv) ); ----FD_ZERO( &SubConnectFds ); --------FD_SET( RecvSock, &SubConnectFds ); ----listen( RecvSock, 5 ); ----vector<unsigned int> thID; ----vector<HANDLE> hTh; ----struct timeval tv; --------tv.tv_sec = 0; --------tv.tv_usec = 0; ----while(1) ----{ --------memcpy( &ConnectFds, &SubConnectFds, sizeof(fd_set) ); --------select( 0, &ConnectFds, NULL, NULL, &tv ); --------if ( FD_ISSET(RecvSock, &ConnectFds) ) --------{ ------------SendSockBuf = accept(RecvSock, (struct sockaddr *)&Send, &len); ------------if( SendSockBuf != INVALID_SOCKET) ------------{ ----------------SendSock.push_back( SendSockBuf ); ----------------thID.push_back( hTh.size() ); ----------------hTh.push_back( (HANDLE)_beginthreadex(NULL, 0, Patch, &SendSock[hTh.size()], 0, &thID[hTh.size()]) ); ------------} --------} ----} ----closesocket(RecvSock); ----WSACleanup(); ----return 0; } unsigned __stdcall Patch( void *Sock ) { ----SOCKET *SendSock = (SOCKET *)Sock; ----send( *SendSock, Ver, 5, 0 ); ----char Str[5]; ----while( Flag == 0 ) ----{ --------recv( *SendSock, Str, 5, 0 ); ----} ----closesocket( *SendSock ); ----return 0; } 以下のようなクライアントプログラムで文字を送信すると、 #include <WinSock2.h> using namespace std; void main() { ----WSADATA wsaData; --------WSAStartup( MAKEWORD(2,0), &wsaData ); ----SOCKET Sock = socket( AF_INET, SOCK_STREAM, 0 ); ----struct sockaddr_in Addr; --------Addr.sin_family = AF_INET; --------Addr.sin_port = htons(55555); --------Addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); ----connect( Sock, (struct sockaddr *)&Addr, sizeof(Addr) ); ----char str[5]; ----recv( Sock, str, 5, 0 ); ----send( Sock, "0.00", 5, 0); ----shutdown( Sock, 2 ); ----closesocket( Sock ); } クライアントプログラムは終了しているのにサーバープログラムは"0.00"を受信し続けます。 どこがおかしいのか分からないので教えてください

  • winsockを使った通信方法

    送信側 #include <winsock2.h> #include <string.h> int main() { WSAData wsaData; SOCKET sock; struct sockaddr_in addr; int len; typedef struct recv { char Name[32]; int Flag; } RECV; RECV send; WSAStartup(MAKEWORD(2,0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); strcat(send.Name, "ABC"); send.Flag=12; len=sizeof(send); sendto(sock,(char *)&send,len, 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(sock); WSACleanup(); system("pause"); return 0; } 受信側 #include <stdio.h> #include <winsock2.h> #include <string.h> int main() { typedef struct rcv { char Name[32]; int Flag; } RECV; WSAData wsaData; SOCKET sock; struct sockaddr_in addr; int len; RECV rcv; WSAStartup(MAKEWORD(2,0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.S_un.S_addr = INADDR_ANY; bind(sock, (struct sockaddr *)&addr, sizeof(addr)); len=sizeof(rcv); recv(sock,(char *)&rcv, len, 0); printf("%s [%d]\n",rcv.Name,rcv.Flag); closesocket(sock); WSACleanup(); system("pause"); return 0; } winsockを使ったUDP通信プログラムで構造体データを送る事が出来ないのですが どこに誤りがあるのでしょうか? コンパイルは通ってるのですが、送信側を起動しても受信側で受け取ることが出来ていない状況です。

  • Winsockについての質問

    Winsockで、「GET / HTTP/1.1」というリクエストを「127.0.0.1(自分自身)」に送って(サーバーはAPACHE2)ドキュメントルートにある「index.html」を見る。 というプログラムを作ったのですが、受信ができません。 受信できるにはどうすればいいか教えてください。 尚以下がそのプログラムです。 #include<stdio.h> #include<winsock2.h> int main(){ SOCKET hsock; struct sockaddr_in serverOption; char buf[1024]; int Error; int func_Error; WSADATA wsadata; func_Error=WSAStartup(MAKEWORD(2,0),&wsadata); if(MAKEWORD(2,0)!=wsadata.wVersion){ fprintf( stderr, "Winsock version error\n"); return -1; } hsock=socket(AF_INET,SOCK_STREAM,0); if(!hsock){ printf("ソケット作成エラー"); } serverOption.sin_family=AF_INET; serverOption.sin_addr.s_addr=inet_addr("210.81.150.5"); serverOption.sin_port=htonl(80); func_Error=connect(hsock,(struct sockaddr *)&serverOption,sizeof(serverOption)); if(!func_Error){ printf("接続エラー"); } func_Error=send(hsock,"GET / HTTP/1.1",strlen("GET / HTTP/1.1"),0); if(!func_Error){ printf("データが送れない。残念ですた"); } Error=recv(hsock,buf,sizeof(buf),0); if( Error <= 0) { printf("受信不可能"); return -1; } buf[Error]='\0'; printf("%s",buf); closesocket(hsock); WSACleanup(); return 0; }

  • Winsockプログラムの初歩的質問(connect()がうまくいかない)

    ソケットの練習をしています。とりあえずconnect()で通信経路を確立するところまでを書いたつもりですが、以下プログラムを実行すると「サーバーソケットに接続失敗」となります。 とりあえずprintf()でチェックしたところsocket()まではうまくいっているようです。 環境:Win2000 , VC++6.0 , LAN接続でDHCP→学内サーバー です。 よろしくお願いします。 #include<winsock2.h> #include<stdio.h> int main() { WSADATA wsaData; struct hostent *host; SOCKET sock1; SOCKADDR_IN name; WSAStartup(2 , &wsaData); host=gethostbyname("www.goo.ne.jp"); //gooのIPアドレスを取得 sock1 = socket(AF_INET,SOCK_STREAM,0); //ソケット生成 /**ここからがあやしい**/ name.sin_port=htons(80); name.sin_addr=*((in_addr *)*host->h_addr_list); if(connect(sock1,(PSOCKADDR)&name,sizeof(name))){ printf("サーバーソケットに接続失敗\n"); return 0; } WSACleanup(); return(0); }

  • Cプログラム UDP送信の送信データに関して

    以下の2つのプログラムでの質問なのですが、 #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") int main() { WSADATA wsaData; SOCKET sock; struct sockaddr_in addr; WSAStartup(MAKEWORD(2, 0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(3054); addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.3 "); sendto(sock, "\x42\42\0\0\0\0\2\0\1\2\x44\x33\5", 13, 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(sock); WSACleanup(); return 0; } と #include <winsock2.h> #pragma comment(lib,"ws2_32.lib") int main() { WSADATA wsaData; SOCKET sock; struct sockaddr_in addr; WSAStartup(MAKEWORD(2, 0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(3054); addr.sin_addr.S_un.S_addr = inet_addr("192.168.0.3 "); sendto(sock, "HELLO", 5, 0, (struct sockaddr *)&addr, sizeof(addr)); closesocket(sock); WSACleanup(); return 0; } について、送信データ部分に「¥」入ることによって、送信プロセスでどのような処理がなされているのですか? ¥~¥までで1バイトということで処理してくださいね、と処理系?に指示しているのですか? また、「¥」はC言語ならではの表記の仕方なのですか?少し、伝えるのが難しいですが、何でもいいのでご回答頂けませんか?宜しくお願いします。

  • Winsockを用いてデータを交互に送信しあいたい

    チャットプログラムではないのですが、チャットプログラムのソースが参考になると思いネットで調べて見ましたが見つからなかったので質問させていただきます。 したいのは、.rarなどの圧縮されたファイル(サイズはGB単位)の送信(TCP)です。 トータルのファイルサイズとファイル名をBYTE配列に書き込む BYTE配列のサイズを送信後、BYTE配列を送信 (とりあえずここでトータルサイズを4MB(4×1024×1024)で割った商をQ、余りをRと置いておく) ファイルをバイナリ読み込みモードで開く 受け取ったという合図を受け取ったらファイルの先頭から4MB読み込んでBYTE配列に入れて送信 受け取ったという合図を受け取ったら続きから4MB読み込んでBYTE配列に入れて送信 ↑を先頭の分も合わせてQ回繰り返す。 受け取ったという合図を受け取ったら続きからRバイト読み込んでBYTE配列に入れて送信 ファイルを閉じる としたのですが、 ファイルの先頭から4MBは送信できているようなのですが、そこから先に進みません。 具体的には、4MBの受信したという合図を送っても、send関数が-1を返すようです プログラムは以下の通りです Server Winsockの設定やファイルのトータルサイズ云々なので略 listen( RecvSock, 5 ); fp = fopen( FileName, "rb" ); int TotalSend = 0; int i = -1; SendSock = accept(RecvSock, (struct sockaddr *)&Send, &len);//コメントアウトを外す場合はこれはコメントアウト while(1) { //SendSock = accept(RecvSock, (struct sockaddr *)&Send, &len); if( i == -1 ) { send( SendSock, (char *)&FileSize, 4, 0 ); //↓の配列サイズを入れたBYTE配列 send( SendSock, (char *)Buff, Size, 0 );//トータルファイルサイズとファイル名 delete []Buff;//BYTE *Buff = new BYTE[FileSize]としたため } //フラグ受信 { recv( SendSock, (char *)&i, 4, 0 ); } if( i == Q ) { fread( SendBuff, R, 1, fp ); while( TotalSend < R ) { TotalSend += send( SendSock, (char *)&SendBuff[TotalSend], R-TotalSend, 0 ); } } else if( i != -1 ) { fread( SendBuff, SendSize, 1, fp );// SendSizeは4*1024*1024の値を#define while( TotalSend < SendSize ) { TotalSend += send( SendSock, (char *)&SendBuff[TotalSend], SendSize-TotalSend, 0 ); } } printf( "%d/%d\n", i, Q ); } Client //Winsockの設定やファイルのトータルサイズ云々なので略 FILE *fp = fopen( FileName, "ab" ); int Total = 0; for( int i=0 ; i<=Q ; i++ ) { //connect( Sock, (struct sockaddr *)&Addr, sizeof(Addr) ); int Error = FileRecv( Sock, i, Q, R, fp ); if( Error == -1 ) { i--;//エラーが出るのでどこでエラーが出るのか見るために追加 } else { printf( "%d/%d\n", i, Q ); } } int FileRecv( SOCKET Sock, int Flag, int Q, int R, FILE *fp ) { //Winsockの設定をコメントアウト中。外した場合、引数のSOCKET Sockは消す int Total = 0; //フラグ送信 { BYTE buff[4]; memmove( buff, &Flag, 4 ); int Error = send( Sock, (char *)buff, 4, 0 ); if( Error == -1) { return -1; } } if( Flag == Q ){ Buff = new BYTE[R]; memset( Buff, 0, sizeof(Buff) ); while( Total < R ) { Total += recv( Sock, (char *)&Buff[Total], R-Total, 0 ); } fwrite( Buff, R, 1, fp ); delete []Buff; } else { Buff = new BYTE[SendSize]; memset( Buff, 0, sizeof(Buff) ); while( Total < SendSize ) { Total += recv( Sock, (char *)&Buff[Total], SendSize-Total, 0 ); if( Total == -1 ) { delete []Buff; return -1; } } fwrite( Buff, SendSize, 1, fp ); delete []Buff; } // closesocket(Sock); // WSACleanup(); return 1; } 毎回切断してもう一度接続しなおすようにしても(コメントアウトを外す)結果(エラー部)は変わりません。 どこが悪いのか見ていただけないでしょうか?

  • 多人数のチャットソフトを考えています

    winsockを使ってプログラミングしています。 1対1のチャットはできたのですが、サーバを挟んで1対多のチャットがうまくいきません。 サーバがクライアントごとにスレットを作って、acceptするたびにできるディスクリプタを配列に格納して、それを元に送信してきたクライアント以外に送るということをしたいと思っています。 説明下手ですいません。。。。 サーバ↓↓↓ ・・・・・・・・・初期化は略・・・・・・・・・・・・・・・・・・・・ while(1){ Csock[i] = accept(s,(struct sockaddr *) &Saddr, &Ssize); CreateThread(Csock[i]);  //クライアントごとにスレッドを作ってるつもり i++; } /**CreateThreadで作るスレッド**********/ unsigned __stdcall recvthread(void *lpx) //lpxにはクライアントのディスクリプタを格納 { fd_set fds, readfds; int sock = *(int *)lpx; int recvSize; char recvbuf[256]; FD_ZERO(&readfds); FD_SET(sock, &readfds); while(1) { memcpy(&fds, &readfds, sizeof(fd_set)); memset(recvbuf, 0, sizeof(recvbuf)); select(0, &fds, NULL, NULL, NULL); if (FD_ISSET(sock, &fds)) { WaitForSingleObject(mutex, INFINITE); recvSize = recv(sock, recvbuf, sizeof(recvbuf), 0); Send(sock,(const char)recvbuf); ReleaseMutex(mutex); if(recvSize == 0) { printf("通信終了\n"); closesocket(sock); break; } if(recvSize == -1) { printf("socket errer (recv)\n"); closesocket(sock); break; } } } return 0; } void Send(int sock,char recvbuf) { for(int j=0;j<5;j++) { if(Csock[j]==sock) continue; send(Csock[j],(const char*)recvbuf,sizeof(recvbuf),0); } } これを実行するとスレッドが無数に作成され、強制終了させられてしまいます。 初級者なのでプログラムのミスがあったら教えて下さい。 違うアイディアもあったら教えて欲しいです。見にくいと思いますがよろしくお願いします。。。。

  • while文とif文

    #include <stdio.h> void main() { char str[2][6] = {"hello","lop"}; int i = 0; while(i < 2){ printf("%s\n", str[i++]); } } 上のプログラムの条件判定の部分にif文を つかうとhelloという文字列しか出力されず while文を使うとhelloとlop 二つ出力され ます。上の条件判定のif文にした時ととwhile 文にした時の違いはどこなのでしょうか?? どなたかご教授よろしくお願いしますm(_ _)m

  • recv関数でフリーズしてしまう

    現在Winsockを用いた簡単なパケット送受信のソフトを作成しています。 開発環境はVisual Studio2008で、ダイアログベースで作成しています。 パケットの受信側の処理なんですが、いつパケットが来てもいいように、 Ontimerで、定期的に受信処理をしようと思っています。 そこでOntimer内に以下のようにプログラムしたところ、コンパイルエラー はないものの、数秒経つと応答なしとなりフリーズしてしまいます。 原因を探ったところrecv関数が原因で、recv関数をコメントアウトした ところ、フリーズはしなくなりました。また、エラー処理は省略していま すが、ソケットの作成失敗などはありませんでした。 なぜrecv関数でフリーズが起きてしまうのか、原因が分かる方は いらっしゃいますか? OnTimer(UINT nIDEvent){ WSAData wsaData; SOCKET sock; struct sockaddr_in addr; char buf[2048]; WSAStartup(MAKEWORD(2,0), &wsaData); sock = socket(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_port = htons(12345); addr.sin_addr.S_un.S_addr = INADDR_ANY; bind(sock, (struct sockaddr *)&addr, sizeof(addr)); memset(buf, 0, sizeof(buf)); recv(sock, buf, sizeof(buf), 0); closesocket(sock); WSACleanup(); }

  • 中身が同じような関数を一つの関数にしたい

    void C_Commu::Recv( vector<void *> Data ) { ----BYTE *Buf; ----int TotalSize, RecvSize; --------TotalSize = Data.size()*sizeof(Data[0]); --------Buf = new BYTE[TotalSize]; --------while( RecvSize < TotalSize ) --------{ ------------RecvSize += recv( Sock, (char *)Buf, TotalSize-RecvSize, 0 ); --------} --------memcpy( &Data[0], Buf, TotalSize ); } このような関数を作ってみたのですが、 C_Commu::Recv( Data->CharaNum ); //vector<char> CharaNum C_Commu::Recv( Data->Model ); //vector<S_Model> Model(S_Modelは構造体) としてみると 'C_Commu::Recv' : 1 番目の引数を 'std::vector<_Ty>' から 'std::vector<_Ty>' に変換できません。 とエラーになります。 使いたい動的配列が違うだけで残りは同じ関数なので一つに纏めてみたのですがどうしてエラーになるのか分かりません。 どのようにしたらいいのでしょうか?

専門家に質問してみよう