• 締切済み

【CAsyncSocket::OnReceive()呼び出しが遅れる?

【CAsyncSocket::OnReceive()呼び出しが遅れる?】 MFCのCAsyncSocketを使ってTCP/IPクライアントアプリケーションより、 別マシン上のサーバアプリケーションに対して、以下の手順で非同期通信をおこなっています。 【クライアント】※以下CAsyncSocketの派生クラス関数です 接続:Connect() 電文送信:Send() *送信通知:OnSend() ※送信しきれなかったデータ送信 (実際には送信処理の分割は発生していません) *受信通知:OnReceive() 電文受信:Recv() ※ヘッダ部約60バイト分受信 受信通知:OnReceive() -----------複数回受信を想定 →電文受信:Recv() ※残りのデータ受信 ↓ (データ受信完了後) 通信終了:ShutDown() 切断:Close() クライアントから送信する電文データサイズは6000バイト弱の固定長です。 サーバから返信される電文データサイズは6000バイト弱または100バイト弱どちらかの固定長です。 サーバアプリケーションは、クライアントからの電文受信後すぐに応答電文を返信しています。 現在、*印のOnSend()呼び出し~OnReceive()呼び出しの間で、ある環境では3、4秒程度必ずかかります。 (受信電文データサイズ6000バイト弱・100バイト弱どちらも発生します) ヘッダ部約60バイト受信後は、遅れは発生していないようです。 CAsyncSocket::SetSockOpt()で送信・受信バッファサイズを65537バイトに設定してみたのですが、 改善されませんでした。 同じ(と思われる)環境を自作して(サーバアプリはテスト用自作アプリ)試してみたのですが 今のところ再現しません。 SocketDebuggerFree(http://sdg.ex-group.jp/)を使用して同じ電文データをサーバアプリに 送信してみたところ、上記のような遅延は発生せず送信後すぐに応答電文受信処理が実行されました。 パケット分割が発生しているようで、6000バイト弱のデータを3回に分けて受信しています。 クライアントアプリでもそのように分割受信されることを想定したのですが、ヘッダ部を受信した 後に1回のOnReceive()内で残りのデータすべてをReceive()によって受信しています。 (自作環境では、ヘッダ部受信後OnReceive()×2回で残りのデータを受信しています) ちなみに、クライアントマシンよりサーバマシンに社内LANを経由して接続してみたところ、 *印間の処理で2秒程度の遅延が発生します。SocketDebuggerFreeでは遅延が発生しません。 試しに、CSocketクラスとCSocketFileクラスを使用して以下の手順で処理を実行してみましたが、 同様に*印の処理の間で3、4秒程度の受信遅れが発生しました。 CSocket::Create() CSocket::Connect() *CSocketFile::Write() *CSocketFile::Read() ※ヘッダ部約60バイト分受信 CAsyncSocket::IOCtl(FIONREAD, XXX) ←※必要なデータサイズ分受信可能になるまでループ CSocketFile::Read() ※残りのデータ受信 : 上記のソケット関連関数をAPIの関数に入れ替えてみたのですが、変わりはありませんでした。 自作環境では、受信遅れは発生していません。 遅れが発生する環境の詳細がわからないので恐縮ですが、なにかお気づきの点をご指摘いただければ 幸いです。 開発環境 OS:Windows XP Professional Version 2002 SP3 Microsoft Visual C++ .NET クライアントアプリの運用環境 OS:Windows Server 2003(SP2?) サーバアプリの運用環境 不明

みんなの回答

  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.1

>なにかお気づきの点をご指摘いただければ その回線で多数の通信が行われていれば普通に遅延が発生する 可能性はあると思いますが (どこか壊れかけてて再送繰り返してるとか) サーバマシンとクライアントマシンは同一LAN上に存在しているのでしょうか? (そうだとするとサーバの運用環境が分からないってのも謎ですが) 環境・アプリによるので一概に言えませんが 遅延が無い前提で考えるのが間違ってるような気もします

pikkutiikeri
質問者

補足

早速のご回答、どうもありがとうございます。 > サーバマシンとクライアントマシンは同一LAN上に存在しているのでしょうか? はい、そのとおりです。 ただ、サーバマシンおよびアプリケーションは別会社が管理されているため、詳細が確認できません。 > 遅延が無い前提で考えるのが間違ってるような気もします おっしゃるとおりです。。。 当方のクライアントアプリケーションとの通信では、受信処理まで毎回3~4秒の遅延が発生するのですが、フリーのSocketDebuggerFree(開発環境:Visual Studio C++ 6.0)との通信は、毎回すぐに(秒単位の遅延が発生することなしに)応答電文の受信処理が実行されています。 (両アプリとも、同じクライアントマシンにて実行しています) そのため、プログラム上になにか問題があるような気がして質問させていただきました。 わからないことだらけで申し訳ございません。またなにかアドバイスいただければうれしいです。

関連するQ&A

  • ソケット通信のシミュレータツールについて

    ソケット通信を使用したクライアント機能のテストを行うために、サーバ側を シミュレートするツールを探しています。 必要なツールの条件は、 『クライアント側から送信された電文をそのままの内容で自動で返す』 シミュレータです。 クライアントの送信データの中で動的にインクリメントしている番号があり、 サーバ側ではその番号をそのまま返す必要があるためです。 クライアントからの電文送信量も多いため、ツールの機能として、受信したデータに 対して折り返しのデータを事前に指定しておくというものではなく、 単純に同一データを自動で折り返すというものが望ましいのですが・・・。 どなたか良いツールをご存知ないでしょうか?

  • CSocket通信での待機処理について

    VC++2008にて、サーバとクライアントPCにて、相互通信を行うプログラムを作成しています。 クライアントは、CSocketを利用しマルチスレッドにて通信を行っています。 thread_start→マルチスレッド作成→ CSocket::Sendでサーバへメッセージ送信→ CSocket::OnReceiveでサーバのメッセージ受信→ サーバメッセージから処理実行と言った流れです。 通常の処理は、この流れで問題ないのですが、 ある処理の場合、thread_startをforループで数回繰り返す 処理を行っています。 この時、データにタイムラグが出てしまうため、 thread_startから処理実行までの一連の流れが終了するまで、 次のthread_startは呼ばれずに待機させたいのですが、 どのようにすれば良いのかが分かりません。 Sendを呼んだタイミングで、 WaitForSingleObjectでスレッドのハンドルを渡したり、 CreateEventでイベントハンドルを渡したりしてみたのですが、 WaitForSingleObjectを呼ぶと、OnReceiveで受信する前で 止まってしまうため、そのままフリーズ状態になってしまいます。 どのタイミングでWaitFor~を呼ぶべきなのか、 もしくは、何か別の手段があるのでしょうか?

  • writeで止まります

    C++でクライアントとサーバを作ってみました。クライアントが送信したものをそのまま、サーバが返す処理です。クライアントから512byteを10000件送信しようとしたのですが、1850件までwriteしてを使っているのですが、512byteのデータを170件ほど書き込んだ段階でwriteでストップし、サーバ側は802件受信して送り返そうとした段階でwriteでストップしてしまいます。 SO_SNDBUFとSO_RCVBUFのサイズは1000000000ほどに設定しています。何が詰まってしまっているような感じですが、何が悪いか不明です。御教授ください。

  • Winsockで1460Byte以降のデータが細切れに

    度々お世話になってます。 VB6.0、Winsockで、チャットプログラムを作っているのですが・・・ 20文字のヘッダーで、処理が識別されるプログラムを作っているんですが、1460バイトを超えるデータが途中で切れて、ヘッダー無しの状態になって、処理を識別できないんですが・・・。 1460という数字は、DataArrivalのbytesTotalで調べたのですが、制御コード(のバイト数)とか、決まっているのでしょうか? Send メソッドで通信する場合、一度に送るサイズを1460バイトにしたいのですが、サーバ←→クライアント間で、自力で作るしかないですかね・・・? データを分割して、配列 myArray(partNum) にする。 先ほどと同じ処理のACKをクライアントが受信したら、partNumを+1して、データを送信。 client.SendData <処理A> 1:○○ server.GetData <A> 1:○○ server.SendData <A> 1:ACK client.SendData <A> 2:●● ・ ・ ・ client.SendData <A> 9999:End 方向性はあってますかね? なにか、楽な方法ありませんか?(汗) cf. http://bbs.wince.ne.jp/ch1/mqbbs.cgi?MODE=MSG&NUM=5156&FILE=bbs.log.51 http://bbs.wince.ne.jp/ch1/mqbbs.cgi?&FILE=bbs.log.51&MODE=MSG&NUM=5161

  • UDPソケット通信におけるデータパケット

    UDPソケット通信をする際、受信データサイズとして考慮するべきサイズはアプリサイズとUDPヘッダー(8バイト)としてソケットオプションで受信バッファサイズを増加させたのですが、予想より受信できるパケット数が少ないです。 例) 1パケットのアプリサイズを10バイトしUDPヘッダーも考慮して実際1パケットあたり18バイトとして、最大5パケット受け取れるようにソケットオプションで アプリサイズ(10バイト)× UDPヘッダー(8バイト)×パケット数(5) 上記のように設定したのですが、実際5パケットも受信できませんでした。 上記のほかにIPヘッダーなども考慮しなければならないのでしょうか? 開発環境:solaris8 C言語

  • 受信待機

    こんばんは。 現在通信機能をもつアプリケーションを作成しています。 CSocketを使用して、同期通信です。 質問です。 クライアントから、サーバにメッセージを投げます。 するとサーバはこのメッセージを解析して、ローカルで処理をし、その結果をクライアントに返します。 問題なのは、クライアントでは、サーバからの結果を受信してからその次の処理を行いたいので、受信待機したいのですが、その方法がわからないのです。 このような処理の方法をご教授ください。 よろしくお願いします。

  • Sql Server 2005 でデータ抜けについて

    お世話になります。 クラサバを構築しているのですが、クライアントよりデータをサーバに登録する際、VB6 SP4のアプリでバッチ処理を行っております。1電文目(サーバのストアドプロシジャを起動)のみ、サーバ(Sql Server 2005)に更新できません。2電文目からあとは、正しく更新されています。 以前は、クライアント側のプログラムは同じだった状態で、サーバのデータベースは、SqlServer 7.0で運用しておりました。その際は、全く問題なく更新できておりました。 また、SQLSERVER2005でサーバ側のプロファイラを使用すると、1電文目も正しく残っています。 このような現象・対処方法等ご存知の方はいらっしゃいませんでしょうか。 よろしくお願いします。

  • Socket通信で、通信終了のイベントが発生しない

    クライアント(Windows)とサーバ(Unix)とSocket通信をするアプリを作っています。処理内容はクライアントのデータファイルをサーバに送信(アップデイト)し、サーバ側でデータを解析し、その結果を印刷するという手順です。 WinSockを使って、送信そのものはうまくいくのですが、サーバでデータを解析し結果を印刷するのに時間がかかり(10秒以上)、その間は送信終了のイベントが発生しません。これはサーバ側での処理を exec関数とwait関数で行っているので、正しい事態なのですが、データの送信が終わったら後はサーバ側で勝手にやって欲しいのです。サーバでの処理を system関数に置換えたり、バックグランド処理にしてもやはり処理が終わるまで送信終了のイベントが発生しません。何かいい方法をお教えください。

  • HTTPサーバプログラム

    C言語でHTTPサーバを作ろうとしています。 大方動くのですが、Java Applet(Jarファイル)を埋め込んだWebページをクライアント側のブラウザに表示させようとすると、エラー(ClassNotFoundError)が発生してしまいます。 ※GIFファイルなどの表示はうまく動いています。 パケットキャプチャソフトなどを活用して色々調べてみると、サーバ側からクライアント側へJarデータを送信する処理が上手く動いていないようです。 今のHTTPサーバの制約で、データ送信関数で一度に送信できるサイズが32KB程度になっています。 Jarファイルがこの最大サイズ(32KB)以下であれば問題なくクライアント側でJava Appletが起動するのですが、このサイズを超えるJarファイルの場合に先のエラーが発生してしまいます。 ※例えばJarファイルサイズが50KBの場合は、データ送信関数を2度呼び出す処理になります(1回目は32KB送信、2回目は残りの18KBを送信します)。 パケットキャプチャソフトでデータの流れを確認すると、50KBのJarファイル・データはクライアント側へちゃんと送信されているように見えるのですが、Jarファイル・データがクライアント側へ送信された後、(恐らく、クライアント側でJarファイルが正しく受信されなかったと認識されているため)クライアント側はClassファイルをサーバ側へリクエストしに行っています。 ※<applet archive="test.jar" code="test.class">としている場合は、"test.jar"ファイルのデータ送信後、クライアント側から"test.class"をサーバ側へリクエストしに行っています。 50KB程度のGIFファイルなどは、分割送信処理を用いてちゃんとクライアント側のブラウザで表示できているのですが…Jarファイルはなぜ上手くいかないのか分かりません。 Jarファイル・データ送信時には何か特別な制約があるのでしょうか? どなたか詳しい方がおられましたらお教えいただきたく存じます。

  • VC++ 6.0 のソケット通信について

    VC++6.0にてソケット通信プログラムを作成中(学習中)なのですが 以下のようなソケットのやり取りを想定しています。 A→B→C A←B←C 分かりづらいかもしれませんが、A,B,C三つのプログラムがあり まず、AはBに向けて電文を送信、Bはそれを受信し、Cに電文を送信 Cはそれに対してBへ電文を送信、BはCからの電文を受信しAへ電文を送信 こんな感じになっています。いうなればA,C間の中継器のような役割をBに持たせたいのです。 http://blog.livedoor.jp/akf0/archives/51585502.html ここのソースなどを参考にしてBのプログラムを組んでいるのですが サーバとクライアントでソースが分かれています。 Bはサーバもクライアントも兼ねるような仕様なのですが、この場合に使用するソケットは (1)Aからの受信を行う(待つ)ソケット (2)Cへ送信を行うソケット (3)Cからの受信を行う(待つ)ソケット (4)Aへ送信を行うソケット の4つのソケットが必要になるのでしょうか? ソケットの仕組みがうまく理解できていないので頓珍漢な質問かもしれませんが 回答よろしくお願いします。

専門家に質問してみよう