• ベストアンサー

VC++ Socket受信中のイベント取得方法について

<現状> 無限ループ内で、以下の処理を行っているのですが、 その間、ウィンドウメッセージを受付けなく、 アプリケー ションの終了もできない状態です。   ソケットを生成(socket)    ↓   ソケットをサーバに接続(connect)    ↓   データ受信(recv)    ↓   取得したデータをファイルへ出力 <質問> ソケット処理中、ウィンドウズイベントを取得できる方法ってありますでしょうか?

noname#8118
noname#8118

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

#1です。 MFCでないとのことなので とりあえず、ですが…。(^^; 非ブロッキングのソケットは使うのをやめて… 以下のようにしたらメッセージ処理はできますよ。(たぶん) 切断ボタンが押された場合に切断ボタンフラグをオンにしてください。 MSG message; while(true) {  // これでメッセージ処理を可能にする。  while(::PeekMessage( &message, NULL, 0, 0, PM_NOREMOVE))  {   DispatchMessage(&message);  }  // 切断ボタン押下判定処理  if(切断ボタンフラグ) {   break;  }  // 受信処理  if(受信完了) {   break;  } // 画面表示処理 }

その他の回答 (3)

  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.4

ブロッキングソケットを使った場合、connect()とrecv()(質問文には無いがgethostbyname()でもブロッキングは発生する)でブロッキングが発生するために、GUIアプリケーションでシングルスレッドの場合ブロッキングソケット通信は推奨されません。 要するに、recv()やconnect()でサーバーからの応答を待っている最中はメッセージ処理が出来なくなってしまうのです。 もっとも顕著に問題となるのはサーバーが応答せず、タイムアウトする場合です。 この場合、タイムアウトで関数が終了するまでの間は【フリーズ?】と思えるほど画面更新が止まります。 MFCを使わずとも非ブロッキングソケット通信は可能ですが、難易度が高い上にキャンセル処理の遅延などの問題を抱えているために、こちらもお勧めできません。 MFCで非同期ソケットするか、スレッド分割が正しいと思うんですが…。

  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.2

Socket通信の基本は以下の2パターン ・非ブロッキングソケットを使う #1さんが紹介されています。 ・ブロッキングソケットを別スレッドで使う そのまんま。スレッドを分けちゃう方法です。 UIスレッド(メインスレッド)でイベント処理をする。 通信スレッドでSocket通信する。 スレッドに関するサンプルはMSDNにもあります。

回答No.1

CAsyncSocket を使ってみてください。これだとブロックしないので他の処理が可能になります。ただ、コールバックの処理などが必要になるので、CSocket 使うよりかは難易度は多少(多少ですよ)上がります。 また無限ループ内でメッセージ処理を行いたい場合は 以下のようなコードをループ内に挿入しておけば可能です。 MSG message; while(::PeekMessage( &message, NULL, 0, 0, PM_NOREMOVE)) { if ( !AfxGetApp()->PumpMessage( ) ) { ::PostQuitMessage(0); break; } }

noname#8118
質問者

補足

折角教えていただいたのに、うまく使えないです。。。 プログラム内容は、 ある受信データから常時受信して、 そのデータを画面に表示。。。 画面のオブジェクトは以下です。 ・接続ボタン ・切断ボタン ・取得したデータを表示するスタティックテキスト プロジェクトはwin32 Applicationでの開発なのですが purojectがMFCでは無い為なのか、CAsyncSocketやCWinApp*を使うとエラーになってしまうんです。 win32 Applicationではうまくいかないのでしょうか・・・。

関連するQ&A

  • IO-Socketで…

    最初に開かれた1つのソケットで、 サーバーから不定期に送られてくるデータを処理→表示しつつ、 ユーザーから入力があった場合にそのソケットへ送信するといったメッセンジャーを作ろうと思っているのですが、「入力待ちと受信待ちを同時に進める」という事がどうも上手くいってくれません… use threads;を使い、送信用・受信用と分けたのですが、やはりどちらか一方が止まってしまいます…。 どの様に書いたらよいのでしょうか… 何方かご教授下さい…。 use threads; use IO::Socket; ($test_socketを生成) sub send{ while($input = <STDIN>){ chomp($input); print $test_socket "$input"; } sub recv{ while(1){ if($receive = <$test_socket>){ print "$receive\n"; } } } my $sendthread = threads->new(\&send); $sendthread->join(); my $recvthread = threads->new(\&recv); $recvthread->join();

  • Perlでイベント処理?

    ようやくPerlに慣れてきて、ふと思ったのですが VBではイベントというものがあり、Perl Tkでもキーボード・マウスのイベントの処理ができる みたいですが、クライアントでソケット受信した場合、いつ受信するかわかりませんので ループしていれば良いのですが、ループしている間は、他の実行が何も出来ず効率も悪いなと 思うようになりました。 WindowsのPerl5.6を使っているのですが、ソケット等、イベント処理できる方法はあるのでしょうか?

    • ベストアンサー
    • Perl
  • Socketによるデータ読み出しについての疑問

    horagaiです。お世話になっております。 socketを使ってWebサーバーからHTTPでファイルを取得するスクリプトを組んでいます。 (1) while(<SOCK>){ push(@Data,$_); } というルーチンでソケットハンドル<SOCK>から読み出したデータをリスト@Dataに入れています。 ここで読み出すのがテキストファイルなら、ファイルデータが終了した時点でちゃんとWhileループが終了するのですが、GIF,JPEGのようなバイナリーファイルの場合、あるいはテキストファイルでも一番最後の行に改行コードが入っていない場合、ループが終了してくれません。どうやってデータの終了を確認してwhileループを終了したら良いでしょうか。 (2) こうやって取得したファイルデータを print @Data ; で表示させると、各行の先頭に半角スペースが入ってしまいます。これはpushかsocketの仕様によるものでしょうか。それとも私がどこかでミスをやっているのでしょうか。 Perlのバージョンは 5.004_04 OSはLinuxです。よろしくお願いします。

  • SocketのSend関数でのCLOSEの検知 [Linux]

    Linux環境でSocket(dm:PF_INET,type:SOCK_STREAM)を使用しての、 Client&ServerプログラムをCで作成しているのですが、 そこでのSend関数の使い方についてご助力ください。 Client&Serverプログラムは下記のような動きをします。 [Client] ServerへConnectした後、複数のDataを数秒間隔でServerへ 送信(send関数使用)します。受信(recvやread関数等)は、 一切行いません。 [Server] ClientからのConnectを受け付けた後、Clientから受信(recv関数 使用)したDataを標準出力へ表示する。送信(sendやwrite関数 等)は、一切行いません。 さて、ここでもしClientプログラムがCloseを発行したり、マシン DOWN等の理由でConnectionが切断され、Server側のSocketが CLOSE_WAIT状態になった場合、Bufferに溜まっていたDataを すべて受けきった後、recv関数が0を返してくれるので 相手が終了したことがわかります。 ここからが質問のMainです。 では、もしServerプログラムがCloseを発行したり、マシン DOWN等の理由でConnectionが切断され、Client側のSocketが CLOSE_WAIT状態になっても、CLOSE_WAIT直後のsend関数が なぜか正常に処理されてしまいます。無論このDataは、 Server側は受け取りません。この次のsend関数実行時に EPIPEが返ってくるので、ここでようやくSocketが切断された ことが判ります。 これを何とかCLOSE_WAIT状態になった直後から、send関数で 切断を検知できるようにできないでしょうか。 よろしくお願いします。 以上

  • Socket通信でのデータの受け渡し

    サーバーが受けたデータを、クライアントに返す プログラムですが、 サーバーは、クライアントからのデータを、 while(true){ BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream())); str=br.readLine(); if(str!=null){ PrintWriter pr=new PrintWriter(s.getOutputStream()); pr.println(str); pr.flush(); }}で、返すようにしています。 クライアントも大体同じです(PrintWriterは、 Buttonを押した時に、取得しています)。 考え方としては、inputstreamは、無限ループで、 取得し、outputstreamは、必要におうじて、取得し データを送っています。 しかし、これだと、一度データを送ると、次から データの受け渡しが出来なくなります。 socketか、inputstreamかoutputstreamのどれかが、 閉じるか、使えなくなるのだと思いますが、 いつもここで、悩んでいます。 (また、無限ループで、BufferedReaderオブジェクト をつくり続けるというのも、ちょっと不安)。 どこに問題があるのか、分かる人教えてください。 お願いします。

    • ベストアンサー
    • Java
  • イベントの取りこぼしについて

    教えて下さい。 VBで構築したアプリケーションにおいて、無限ループ内で処理を判断し、実行するようなプログラム構築にしています。この無限ループ内に「DoEvents」をセットしています。これによりOSに溜まっている、各イベントを処理していると思うのですが、処理するイベントに取りこぼしは発生しないのでしょうか? 現在、A/Dボードを実装しており、2ms周期でVBのイベントが発生するようなソフトになっています。「DoEvents」実行時に、OS側が処理に要する時間は、キューに溜まっているイベント数×1回のイベント処理時間で単純に導けるものでしょうか? また、CPUのスペックを2倍にすると、単純に処理時間は半分と計算できるものでしょうか?

  • LWPでHTML取得(その前にSocket取得)できない

    初めて投稿させていただきます。 宜しくお願い致します。 LWP::Simpleなどを使ってWebサイトのHTMLソースを 取得したいのですが、できません。 同じplファイルを使って環境Aでは取得できているのですが、 環境Bでは出来ません。 LWPのバージョンは5.805で、両環境とも同じです。 どこでエラー?が起こっているかSimple.pmから ソースを追って見たところ、 LWP::Simple::_trivial_http_get( )のSocketを取得する所で undefが返却されているようです。 さらに追っていくと、 IO::Socket::INET::new( ) →IO::Socket::new( ) →IO::Socket::INET::configure( ) 最終的にここまで来ました。 configure( )の、 --------------------------------------------- if ($sock->connect(pack_sockaddr_in($rport, $raddr))) { # ${*$sock}{'io_socket_timeout'} = $timeout; return $sock; } --------------------------------------------- ここまで来て、上記のifブロックに入らず、timeoutかよくわかりませんが、 とにかくソケットを返していないようなのです。 その原因を、お教え頂きたいのです。 環境AとBで違う所は、大きな差としては、 無線LANを使ってない(A)か、使ってるか(B)しか無いです…。 また、環境Bで試した点としては、 ・無線LANルータに対して get('http://192.168.xx.yy');のようにした事と →結果、だめ ・apache tomcatが立ち上がっているローカルホストに get('http://192.168.xx.zz:8080');のようにした事 →結果、だめ です。 長々と状況説明してすみませんが、ご回答お待ちしております。 以上です。

    • ベストアンサー
    • Perl
  • スレッド中でウインドウのイベント(Windows)

    カテゴリー違いかもしれませんが、 Windowsでスレッド中でウインドウを生成すると、 イベントの処理ができなくなります。 (たぶんもとのイベントループにメッセージがいって  そこで終わっていると思うのですが) これを避ける方法とかあるのでしょうか? メインループにメッセージを送ってそこでウインドウを 生成してもらうのが由緒正しい方法なのでしょうか? 用語とかむちゃくちゃかもしれませんが よろしくお願いします。

  • VC++ メインループでのイベント監視方法

    こんにちは。 VC++2008Expressでプログラムをしようと思っている初心者です。 以下、変な疑問があり、お尋ねしたいと思います。 よろしくお願いします。 Windowsアプリケーション Win32API クラスで別スレッドを作成して、そのスレッドからのイベントを WinMainループで受け取る方法ですが 通常皆様はどういう風にするのでしょうか? クラスは、その他のプログラムでも流用可能で様々なアプリに対応しやすいようにしあげたいのですが。。 別スレッドでイベント発生時にWinMainにどのように教えるのが普通のやり方なんでしょうか? 僕の考えでは、WinMain関数内のループ内で常時イベント発生していないか 以下のように監視させるか eventloop el; while(GetMessage(&msg,NULL,0,0)) {   TranslateMessage(&msg);   DispatchMessage(&msg);      if(el::boolEvent){     イベント処理へ   } } とするのが良いか? これだとクラスの関数、変数の使い方さえ分かるようにしておけば流用は簡単 なのかなと思いますが。。 メインのループ内にこんな監視を入れるようなプログラムをみたことないので ナンセンスなのではと思います。 次に考えられるのは、クラスのイベント発生で作成したSendMessageを送って メッセージ処理でイベント処理をさせるのが良いのかなって思いますが これだと、流用するときに対応したMessage(キュー?ですかね)を作成しないといけなく 私的に分かりにくいなーって思います。。。 変なことで悩んで先に進まないのですが、皆様はどのようにコーディングされるのでしょうか? ちなみにイベントというのは、RS232Cで受信があって、そのデータを加工したあとで メモリに格納して格納しましたよってイベントです。 どうかよろしくお願いします。

  • 0byteデータの送信と受信

    現在unixでsocketプログラムを書いています。 FTPライクなプログラムを書いているのですが、ファイルを送受信する場合、ファイルの終端をどうするかを考えています。 ファイルサイズを送るのはなしです。 sendで0byteのデータを送り、recvで0byteのデータを受信した場合にファイルの終端に達したとして処理を終らせたいと考えています。 実際、sendでは0byteのデータを送信してもエラーにはなりませんが、recvでは受信できません。 そのような処理はできるのでしょうか? よろしくおねがいします。