winsock windowprocでFD_WRITEの処理について
- 非同期処理でwindowprocでのデータ送信を行っています。
- クライアントからサーバへのデータ送信後、サーバはクライアントにデータを送信します。
- しかし、recvされた後にデータが空にならないため、FD_WRITEを実行するタイミングが分かりません。
- ベストアンサー
winsock windowprocでFD_WRITEの処理
すみません。よくわからなくなったので教えてください。 非同期処理を行いwindowprocで送信、受信の処理をしているのですが、一部わかりません。 [内容] クライアントからデータを送信してもらい、サーバ側で受信をして、サーバ側で受信後、クライアントへ送信をしたいのですが.... [サーバ側ソース抜粋] ::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { int EventErrorCoode; int len; switch(message) { case FM_TCPPROC: EventErrorCoode = WSAGETSELECTERROR(lParam); switch(WSAGETSELECTEVENT(lParam)){ case FD_CONNECT: //コネクトされたときの処理 break; case FD_ACCEPT: if(EventErrorCoode != 0){ NetWork_LogOut(); break; } // 状態判定処理 if(NetWork_Accept() == FALSE){ //失敗したときの処理 } break; case FD_READ: // データの受信メッセージ if(NetWork_Recv() == FALSE){ } break; case FD_WRITE: //テスト折り返し送信 SendData = "折り返し"; strcpy(Recv_Buffer,SendData); len = send(server_s, Recv_Buffer, strlen(Recv_Buffer),0); break; : : return CDialog::WindowProc(message, wParam, lParam); } ::NetWork_Recv() { int nResult; int len; nResult = recv(client_s, (CHAR *)Recv_Buffer, RECV_SIZE - 1, 0); Recv_Buffer[nResult] = '\0'; return TRUE; } *非同期処理はsocket作成後しています。 クライアントから送信されたデータが、FD_READで認識し、NetWork_Recv()関数を使って受信します。 その後、空になった時点で、FD_WRITEを実行すると思っていたのですが、recvされた後、データは空にならないのでしょうか?
- poposan
- お礼率48% (64/132)
- C・C++・C#
- 回答数1
- ありがとう数1
- みんなの回答 (1)
- 専門家の回答
質問者が選んだベストアンサー
あーあ、WindowProcオーバーライドしちゃってるんだってのはおいといて(^^;; >クライアントから送信されたデータが、FD_READで認識し、NetWork_Recv()関数を使って受信します。 >その後、空になった時点で、FD_WRITEを実行すると思っていたのですが、recvされた後、データは空にならないのでしょうか? FD_WRITEは、「ソケットの送信バッファに空きができたことを通知」なんだから、受信の終了とは関係ないような。 クライアントへデータを投げつけ終わった(残りを投げることができる)タイミングを知るためのものだと思うんですが。 FD_CONNECTの直後、FD_READの前にFD_WRITE来てませんか?
関連するQ&A
- winsock2 非同期処理について
教えてください。 winsockを使用して、ネットワーク間のアプリを作成しているのですが、 wndPorcが処理されないため困っています。 お分かりになる方教えてくださいませ。 送信側はメッセージを送っていますが、受信側のaccept処理が出来ません。(wndProcが呼ばれない) wndPorc関数って呼び出しって必要でしたか??? [環境] OS windows2000 Visual C++ 6.0 MFC [ソース] [.cpp内部] bool CSysCp02Dlg::NetWork_LogOn() { struct sockaddr_in server; // winsock初期処理 // ソケット作成 // 非同期処理 if(WSAAsyncSelect(server_s,this->m_hWnd,FM_TCPPROC,FD_ACCEPT|FD_CONNECT|FD_READ|FD_WRITE|FD_CLOSE) == SOCKET_ERROR){ return false; } // 構造体をクリア // 設定 // bind処理 // 受付開始(listen処理) return true; } LRESULT CALLBACK CSysCp02Dlg::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) <----ここの関数が処理されない。 { struct sockaddr_in client; int n; char Recv_Buffer[RECV_SIZE]; int nLength = sizeof(client); switch(message) { case FM_TCPPROC: switch( lParam ){ case FD_ACCEPT: client_s = accept(server_s, (struct sockaddr *)&client, &nLength); if(client_s == INVALID_SOCKET){ ErrNum = WSAGetLastError(); } break; } } return WndProc(hWnd, message, wParam, lParam); } 800文字以内に入りきらないため、略してあります。
- ベストアンサー
- C・C++・C#
- VC++2008Enterpriseでwinsockを扱っていいるので
VC++2008Enterpriseでwinsockを扱っていいるのですが、 クライアント側(PC)からファイルを読み込んで、ソケットを使って、サーバー側に渡し、何もせず、そのままクライアントに返したものをprintfすると。ファイルの後ろに大量のゴミがくっついて、それの除去ができないのです。 サーバー側では普通に出力できるのですが、何でクライアント側だけ汚いか、よくわからないんです。 送ったファイルはテキストファイルで中身は aaa bbb 111 とこんな感じです。 クライアントのソースは、受信部分を抜粋しますと //ファイルを1行づつ読み込む while((fgets(buffer1, size, fp))!=NULL){ len = strlen(buffer1); sprintf(str,"%4d%s",len,buffer1); //printf("%d行目:バイト数=%s\n%s\n",n,str,buffer1); ok = send(s, str, (int)strlen(str), 0); if(ok==SOCKET_ERROR){ printf("送信できません\n"); exit(1); }else if(ok ==-1){ perror("send"); break; } n++; } shutdown(s,1); while(1){ ok = recv(s, recv_buf, sizeof(recv_buf),0); if(ok == -1) { printf("受信エラー\n"); shutdown(s,2); closesocket(s); break; }else if(ok ==0){ printf("送信終了\n"); shutdown(s,2); closesocket(s); break; }else { printf("%s\n",recv_buf); } } } } これで、出力すると大量のゴミがつくんです。 どなたか、ご指導願い無いでしょうか?
- ベストアンサー
- C・C++・C#
- Winsockでの送受信についての質問
本日はじめてOKwaveを利用させていただきます、Nimameです。 以後よろしくお願いします。 本日はwinsockの送受信について質問させていただきたく、投稿しました。 現在winsockを利用したS/Cのネットワークプログラムを組んでいるのですが、 送受信の時、同PC内だとうまくいき、外部PCからだとうまくいかずに困っています。 送受信の際(recv, send)の後にSleep(10)を入れるとうまくいくことから ・パケットが最後まで送信しきれていない ・パケットが最後まで受信しきれていない の以上が原因かと考えています。 そこでサイズ分最後まで送受信をする関数を用意したのですが、 これがどうにもうまく働いていないようでやはりうまくいきません。 -------------------------------------------------------- // 最後まで送りきる int Send(SOCKET s, char *buf, int len) { int endsize; int r; char* sendptr = buf; // 送信する先頭アドレスを取得 // 確実に全てのパケットを送信する while(endsize < len) { r = send(s, sendptr, len - endsize, 0); // 送信結果がエラーなら終了 if( r <= 0 ) return r; sendptr += r; endsize+= r; } sendptr = NULL; return endsize; } -------------------------------------------------------- // 最後まで受信する int Recv(SOCKET s, char *buf, int len) { // 受信データアドレスの設定 char* recvptr = buf; int endsize= 0; // 受信データを1つぶん読み込むまでループする while( endsize < len ) { // 未受信データアドレスに実際にデータを読み込む int r = recv(s, recvptr, len-endsize, 0); // エラーだったら終了する if( r <= 0 ) return r; recvptr += r; endsize+= r; } strext(buf, buf, 0, len); recvptr = NULL; return endsize; } -------------------------------------------------------- 以上なのですが、おかしな点や、改善点などありましたら お教えいただけたら幸です。
- 締切済み
- C・C++・C#
- winsock recvでデータの取得方法
sendで送られてきたデータをrecvで取得しています。 recvで取得したあと'\0'を入れないと文字化けを起こしてしまうので'\0'を入れているのですが、そうすると送信したバイト数と違ってきます。 同じバイト数にしたいのですが、いろいろ試しましたが、うまくいきません。 ご存知の方いらっしゃいましたら、教えてください。 また、recvで受けるときは、バイト数が多くなるのは、仕方がないのでしょうか? // ------------------ ソース -------------------- DWORD byteResult; ofstream fileWrite; byteResult = 0; while(byteResult < 最大バイト数){ nResult = recv(client_s, (CHAR *)pbuff, 7000, 0); <-- 一括で最大バイト数で受信をしたいのだが、途中で文字化けを起こすので、7000バイトに区切って受信。 pbuff[nResult + 1] = '\0'; try{ fileWrite.open("D:\\suzuki\\LogOutTest\\outdir.txt", ios::app); fileWrite << pbuff; fileWrite.close(); }catch(CException e){ fileWrite.close(); return -1; } byteResult += nResult; } delete[] pbuff; よろしくお願いします。
- ベストアンサー
- C・C++・C#
- キーボード処理 SDK
クライアントがサーバを操るツールを作っています。 何をしたいか↓ ・クライアントはサーバの画面上でメモ帳を開き「日本語」入力をする。 (クライアントからサーバの画面上で「(0~9)(a~z)」は打てます。) □サーバ側 case WM_KEYDOWN: //押されたときの処理 //送られてきたキーイベントの実行 keybd_event(cmsg.wParam,cmsg.wParam,0,0); break; case WM_KEYUP: //離されたときの処理:解放処理 keybd_event(cmsg.wParam,cmsg.wParam,KEYEVENTF_KEYUP,0); break; □クライアント //キーボード処理 case WM_KEYDOWN: 環境 WindowsXP MicrosoftVisualC++ SDK お願いします。
- 締切済み
- C・C++・C#
- ソケットプログラミングのrecv時にFD_READイベントが終わらない
現在Winsockを用いているのですが、クライアントからのデータを受信したときにおこるFD_READイベントをWSAWaitForMultipleEventで受け取って処理しているのですが、recvからの戻り値が常に0にも関わらずFD_READイベントが発生し続けます。クライアント側での送信は成功しています。 このような事態が発生する原因としてはどのようなことが考えられますでしょうか?
- ベストアンサー
- C・C++・C#
- swith文について
こんにちは。 switch文を用いて分岐を行っています。 以下のプログラムは、whileの無限ループ内にswitch文の分岐を行っています。while内にrecvfrom関数(ソケット通信用関数)を用いています。recv_Buf配列内をヌル文字まで走査し、文字列の長さによって分岐をしています。 while内のrecvfromによって、他端末から文字列を逐次受信しているのですが、この場合、switch文ではなくif文による分岐を行うべきなのでしょうか? また、breakを行うことで、whileの無限ループまで抜けることになるのでしょうか? switchの場合、breakを用いないと、実行したくないところまで実行してしまう可能性があるので、breakは必要だと思い以下のプログラムにしました。 よろしくお願いいたします。 [プログラム] while(1){ recvfrom(s2, recv_Buf, (int)sizeof(recv_Buf) - 1, 0, (SOCKADDR *)&from, &fromlen); while(recv_Buf[len]!='\0') len++; switch(len){ case 3: if(memcmp(recv_Buf,"END",3) == 0){ //処理 } break; case 5: if(memcmp(recv_Buf,"START",5) == 0){ //処理 } break; case 12: case 13: case 14: case 15: if(memcmp(recv_Buf,"SEND_PACKET",11) == 0){ //処理 } break; } }
- ベストアンサー
- C・C++・C#
- ~の初期化が 'case' ラベルによって行われませんでした。のエラーについて
よろしくお願い致します。 環境 WIN98 VC++6.0 MFC にて http://www.alpha-net.ne.jp/users2/uk413/vc/VCT_TaskTray.html を参考にタスクトレイアプリケーションを作りました。 下記コードにて、 case WM_LBUTTONDOWN://■追加 break;//■追加 を追加すると、error C2360: 'pPopup' の初期化が 'case' ラベルによって行われませんでした。のエラーが出ます。 どうしてなのでしょうか? お分かりの方お教えください。 ************************* LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { if( message == WM_USER_POPUP ) { // カーソルの現在位置を取得 POINT point; ::GetCursorPos(&point); switch(lParam) { case WM_RBUTTONDOWN: SetForegroundWindow(); // この処理を忘れずに! CMenu menu; VERIFY(menu.LoadMenu(IDR_MENU1)); CMenu* pPopup = menu.GetSubMenu(0); ASSERT(pPopup != NULL); pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this); PostMessage(WM_NULL); // この処理も忘れずに! break; case WM_LBUTTONDOWN://■追加 break;//■追加 } } return CFrameWnd::WindowProc(message, wParam, lParam); }
- ベストアンサー
- C・C++・C#
- CALLBACK 内の DefWindowProc の場所
こんにちは、最近 無料版Borland C++Compiler 5.5 を使って WIN32 API の勉強をしています 気にしなければ別に問題ないのですが、どうしても気になって気持ち悪いので、質問させて下さい 参考書や Web でコード例を見ていると、CALLBACK 内の DefWindowProc関数 を switch の default にする例 と switch の default を書かずに CALLBACK の return にする例があります 好みの問題なのでしょうか? switch は、 default を入れた方が正式と思いますが、default に DefWindowProc を記述すると コードが長くなるにつれ DefWindowProc が switch 内でちょこちょこ必要になってきます 私は、switch の default があった方が良いかなと思い DefWindowProc を default に記述していますが、コードが短くなるなら CALLBACK の return に DefWindowProc を記述しようと思っています どちらが良いのでしょうか? 暇な時でかまいませんので、ご教授下さい 宜しくお願い致します ※DefWindowProc の 記述場所を CALLBACK の return にする LRESULT CALLBACK WindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch(uMsg){ case WM_DESTROY: PostQuitMessage(0); break; } /*基本的なメッセージの処理*/ return DefWindowProc(hWnd, uMsg, wParam, lParam); } ※DefWindowProc の 記述場所を switch の default にする LRESULT CALLBACK WindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch(uMsg){ case WM_DESTROY: PostQuitMessage(0); break; default: /*基本的なメッセージの処理*/ return DefWindowProc(hWnd, uMsg, wParam, lParam); } return 0; }
- ベストアンサー
- C・C++・C#
- CTreeCtrlのCreate関数でエラーになります。
Visual C++ .NET Win32 プロジェクト で、アプリケーションを作成しようと思っています。 #include<afxwin.h> #include<afxcmn.h> // マルチスレッド CTreeCtrl *m_TreeCtrl; LRESULT CALLBACK int WindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { case WM_LBUTTONDOWN: m_TreeCtrl=new CTreeCtrl; m_TreeCtrl->Create(WS_VISIBLE | WS_TABSTOP | WS_CHILD | WS_BORDER | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES | TVS_DISABLEDRAGDROP, CRect(10, 10, 300, 100), CWnd::FromHandle(hWnd), 10000); break; case WM_CREATE: break; case WM_DESTROY: PostQuitMessage(0); break; case WM_PAINT: HDC hDC; PAINTSTRUCT Paint; hDC=BeginPaint(hWnd,&Paint); EndPaint(hWnd,&Paint); } return DefWindowProc(hWnd,message,wParam,lParam); } ・・・ と記述すると、エラーになります。 解決方法を教えてください。
- ベストアンサー
- C・C++・C#
お礼
いつもありがとうございます。 >あーあ、WindowProcオーバーライドしちゃってるんだってのはおいといて(^^;; MFCの使い方よく知らなくて、すみません。(^^; いろいろ事情があり、急遽VC++での開発になったので.... 教えて頂いているのに、本当に申し訳ありません。 いろいろ調べてみたら、sendの使いかたが間違っていました。すみませんでした。 気が焦っていたみたいで、見落としがありました。