• ベストアンサー

TCP/IPで受信エラー

自作Linuxマシン:クライアント、Windows:サーバの組み合わせで、TCP/IPによる大量受信をすると1000回に1回程度 "could not read received packet length error=7"というエラーがでます。実際に受信内容が化けていることも正常なこともあります。 受信側: Linux-2.6.18-at9 Debian。PowerPc 300MHz 100Base 送信側: Vista Ultimate Core-duo 1.2GHz です。 このエラーはGrepした結果、/drivers/net/temac/adaptor.cというデバイスドライバのFifoReceiveHandlerというモジュールが発しているらしいことが分かりました。 受信側プログラム: void* tcpReceiveThread(void* pParam) という受信専用のスレッドを設け、 while(1){ rcvSize = recv(socket, buf, 1024*9, 0); // Blocking Mode  ・・・・データ処理 } で常時待ちます。 Windows側には別のprocess側チャネルで送信要求をだします。 送信側プログラム:  int ok = send(socket_h, buf, 1024*9, 0); これを1回の送信要求に対し2回続けて実行します。 Windows側は同じPortNoでacceptしてあります。 不具合の推定原因: 1.受信側データ処理が重く、2回目の送信データが処理しきれていない。データ処理は1ms程度 2.受信process側の処理が重く、受信スレッドにリソースが回らない。 3.一回の送受信データ1024*9バイトが大きすぎる。あるいは必要な設定を行っていない。 などが考えられます。実行の時間的制約が厳し過ぎるのかもしれません: 受信側マシン全体で13msの間にコアジョブ3msと2個以上のpacket(1024*9)を受信しなければなりません。 ご示唆願えることがあればお願いいたします。

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

  • ベストアンサー
  • unacyo
  • ベストアンサー率51% (35/68)
回答No.1

もしかして、バッファサイズが小さいのかもしれません。 setsockopt()のSO_RCVBUFでソケットの受信バッファサイズを64Kなりもっと大きくしてみたらどうでしょうか?

gammodler
質問者

補足

unacyo様 回答ありがとうございます。 さっそく試みたのですが、つまらないことで中断しています。 int ret = setsockopt( socket, SOL_SOCKET, SO_RCVBUF, (const char*)&sock_buf_size, sizeof(sock_buf_size) ); において initializer element is not constant というエラーがでます。 sock_buf_sizeの定義を const int sock_buf_size = 0x10000; static int sock_buf_size = 0x10000; static const int sock_buf_size = 0x10000; int sock_buf_size = 0x10000; としてみたのですが、いずれもNGでした。 gccに不慣れ、ご示唆願えることがあればお願いいたします。

関連するQ&A

  • TCP/IP のパケットの分断と結合について

    linux で socket を使ってプログラムを作っております。 パケットの頭に、どんな種類のパケットかの情報を入れ、それに続く部分にデータを入れて送っております。受信側では、届いたパケットの頭の情報を見て必要な処理を行う、という流れになっております。 ところが、時々、次のような現象が発生して困っております。 ・送信側で一回のsendで送ったはずのデータが受信側では一回のrecvで届かず、二回のrecvで届く。 ・送信側では二回のsendで送ったつもりなのに、受信側では一回のrecvで2つのパケットが結合したデータが届く。 これはsendとrecvでは普通に起こると想定しなければならない現象なのでしょうか? それとも、linuxマシンの設定に問題があるのでしょうか?

  • パケット受信 recvfrom( )について

    お世話になります。 WinSockを用いてUDPパケット受信プログラムを作成しています。 環境はVC++です。ダイアログベースで、 STARTボタンを押すと受信開始します。 送信側よりパケットを1000個送信した場合、受信側では、 int num; SOCKET sock; char buf[1500]; //ソケットの設定は省略 while(1){ num = recvfrom(sock, buf, sizeof(buf), 0, NULL, NULL);  printf("%d",num ); if( num == SOCKET_ERROR){ break; } } recvfrom()で受信していますが、送信側で送信が完了しても while()を抜けないのか、応答なし(フリーズ)してしまいます。 printf()で表示してみると、 ちゃんと送信パケット個数回表示されています。 送信パケット数は変動するため、受信側のプログラムには 個数がわかりませんため、while()でループしています。 while()を抜ける条件はどうしたらいいのでしょうか? ちなみにrecvfrom()の戻り値として SOCKET_ERROR,0を指定してもエラーになります。 長くなりましたが、どうぞよろしくお願い致します。

  • UDPプログラム、データの送受信

    javaを使って通信の勉強をしています。 UDPを用いた通信のプログラムを作成しています。 送信側では、次のようにして送信したいバイト数を分割して送信しています。 BUF_MAX = 40960; DatagramSocket socket = new DatagramSocket(); // data分のバイトデータを分割して送信する。 int part = 5242880 / BUF_MAX; // 分割して送信する回数 send_start = System.nanoTime(); for(int i = 0;i < part;i++){   byte[] buf = new byte[BUF_MAX];   buf[0] = (byte)i;   DatagramPacket sendPacket = new DatagramPacket(buf,BUF_MAX,serverAddress,servPort);   total += BUF_MAX;   // 指定したバイト数を送信する。   try{     socket.send(sendPacket);   }catch(IOException e){     System.out.println(e);   } } System.out.println(total); このようにしています。 こうする理由は、5242880バイトのデータを128回に分割して送信して、 受信側で受信したパケットの最初の文字を見て、何個目のパケットが届いていないかを確認するためです。 受信側でこれらのデータを受信する方法を考えているのですが、どうすればよいか分かりません。 receive(packet)で受信するのは知っています。 送信された複数のデータを受信するのに、 for(int i = 0;i < 128; i++){  receive(packet); } というようにするのでしょうか?このようにすると、 このループを抜けることができません。それは、パケットが通信途中で紛失するため、128回受信しないからだとおもいます。 受信しなくなったらループを抜けるというようにすればよいとおもいますが、その方法が分かりません。 どなたかアドバイスをいただけないでしょうか?お願いします。

    • ベストアンサー
    • Java
  • TCP通信のプログラム(java)

    javaを使ってTCP通信のプログラムを作りました。 そのプログラムは次のような動作をさせたいですが、途中までしか動作確認がとれません。 1. 送信側で指定したバイト数のデータを送信する。それにかかった時間を計測する。 2. 送信されたバイトデータを受信する。届いたバイト数の確認をするとともに、受信にかかった時間を計測する。 3. 受信側は1.で行った処理と同じようにして、届いたバイト数分のデータを返信する。 4. 3.で送信側に送信されたデータを受信して、受信時間を計測する。届いたバイト数を確認する。 2.までは、正常に動作します。正常な動作とは、 送信側は、指定した数のバイトデータを送信して、それにかかった時間を計る。 受信側は、送信されたデータを受信して、それにかかった時間を計り、届いたバイト数を確認する。ちなみにこの2つの時間はほぼ同じになります。 ここまではできています。 ですが、送信側が受信側で届いたバイト数分のデータを送信し、送信側でそのデータを受信してその時間を測るというコード(//*受信処理*//という行から下)を追加するとうまくいきません。 受信側では、//*受信処理*//という行から下を追加すると、うまくいきません。 送信と受信処理のコードを載せます。 送信側(送信バイト数は入力させます) Socket sock = new Socket(host, port); BufferedOutputStream out = new BufferedOutputStream(sock.getOutputStream()); BufferedInputStream in = new BufferedInputStream(sock.getInputStream()); //*送信処理*// // 送信データを送信する。 int count = 0; // write()の回数 System.out.println("<データ送信処理>"); start = System.nanoTime(); // 計測開始時間 for (int i = 0; i < Data; i++) {   try {     out.write(i);     out.flush();     count++;   } catch (IOException e) {     System.err.println((count + 1) + "つ目のバイト:書き込みエラー");   } } stop = System.nanoTime(); // 計測終了時間 System.out.println("送信完了"); System.out.println("送信されたバイト数:" + count); // 送信スループットを計算する。 // 結果を表示する。 //*受信処理*// // 変数を定義する。 long startNs = 0; // 受信前の時間のナノ秒を返す。 long stopNs = 0; byte[] buf = new byte[1000000]; int total = 0, part; // ストリームの終わりに達し,-1が返されるまで受信する。 System.out.println("<データ受信処理>"); startNs = System.nanoTime(); while ((part = in.read(buf, 0, buf.length)) != -1) {   total += part;   System.out.println(part); } stopNs = System.nanoTime(); System.out.println("受信完了"); System.out.println("受信されたバイト数:" + total); // 受信スループットを計算する。 // 結果を表示する。 // 出力ストリーム・ソケットをクローズする。 out.close(); sock.close(); 受信側のコードは補足欄に載せます。このコードだと、 送信側の計測結果は表示されますが、受信側で受信時間や受信速度などが表示されません。 送信側で通信を強制終了すると、その後に受信側は、結果を表示します。 データを片道ではなく往復させて、それらの処理時間を計測したいのです。うまくいかないのでアドバイスを頂きたいです。 このコードのおかしい部分が分かる方はアドバイスをお願いします。 コードが見にくくて意味がわからないかもしれませんが、そうならば、データを往復させてその時間を測るためのアドバイスをお願いします。

    • ベストアンサー
    • Java
  • TCP/IP受信で原因不明のBeep音

    自作したLinuxマシンからLAN経由で周期的にStatusを吸い上げています。 Linuxマシンがサーバ、Windows側がクライアントです。 最近Windows側がデータを受信する周期に合わせてBeep音がするようになりました。それも最初からではなく、何かの効果が蓄積した後でなり始めます。スピーカ音量をミュートにすれば消え、かつなっているときも受信データ内容は正確な検証ではありませんが、異常は見られません。 TCP/IPパケットの一回の受信量は200バイト以下、周期は50msecと1秒の2種類があり、Beep音の間隔は周期に対応しているようです。 Windows側のプログラムを停止させれば、音は小さくなりますが、Linuxマシンが送信してくる周期に合わせて小さく鳴っています。 原因の分析手法が皆目見当がつきません。可能性だけでもご示唆いただけると助かります。

  • パケット数のカウント方法

    いつもお世話になります。 今、WinSockを用いて、パケット送受信ソフトを作っています。 送信は完成しましたが、受信で問題があります。 UDPプロトコルです。 受信側で受信したパケット数を数えたいのですが、 その方法がわかりません。 送信側で送信するパケットは 複数個で受信側にはそのパケット数はわかりません。 以下のようにカウントすると送信パケット数と異なる 数になります。 int count=0; while(1){ if((recvfrom( recvSocket, buf, sizeof(buf), 0, NULL, NULL)) != SOCKET_ERROR){ count++; } } 受信パケットを数える方法はありませんか? どうぞよろしくお願い致します。

  • UDPで受信スループットを測定

    Javaを使って通信のプログラムを勉強しています。 UDP通信のスループットを測定するプログラムを作成しています。 送信側で5242880バイトを128回に分割して送信して、 受信側でそれらのパケットを受信する時間を計測するプログラムを 作りたいのですが、受信側でどのタイミングで受信処理を止めるのかがわかりません。 start = System.currentTimeMillis(); for(;;){   socket.receive(RecvPacket);   if(ループを抜ける条件)     break; } stop = System.currentTimeMillis(); で受信し続けて、受信するパケットがなくなったらループを抜けるというように考えました。 UDPでは送信されたパケットがすべて届くという保証はないので、 128回受信したらループを抜けるというようにできないので、困っています。 届いたパケットの数も数えて到達率も計算したいです。 受信が終わったら、ループを抜けるというようにしたいのですが、 どうすればよいでしょうか?

    • ベストアンサー
    • Java
  • TCP/IPでのエラーシーケンス

    TCP/IPで1台のサーバSから複数のコンピュータA,B,C...に データを送信している途中で、 Cがハングパップした時のエラーシーケンスを知りたいのですが。 例えば、 サーバSからA,B,Cに1つのデータを複数のパケットに分けて送信するときに、 送信途中でCがハングアップ(通信不能)した場合に、 サーバSがCにパケットを送信しなくなるのは、どのタイミングなのでしょうか? 例えば、5つ目のパケットで通信不能になった時は Cへのそれ以降のパケットを送信しないのでしょうか? 初歩できなことですが、お願いいたします。 ここら辺のことで、参考になる文献がある場合にも教えて頂きたく思います。

  • ソケット通信の受信処理について(マルチスレッド)

    今私はVisual Studio2010 C++で ソケット通信のプログラムをしているのですが、 クライアントから送ってくる文字をうまく受信できません。 接続は出来ています。 _beginthreadexでスレッドを作っています。 以下が受信の処理のスレッドになっています。 unsigned int __stdcall ThSend(void* pArg) {     CSocket_ServerDlg* pDlg = (CSocket_ServerDlg*)pArg; while(1){       char buf[256]; /* 受信するバッファ */ int buf_len; /* 受信したバイト数 */ buf_len = recv(pDlg->m_NewSoc,buf , RECVSIZE - 1, 0); if (buf_len != SOCKET_ERROR ){       buf[buf_len] = '\0'; /* 受信したバッファの後ろにNULLを付加する */       }       pDlg->m_xvEditResult += _T("Recv : ");       pDlg->m_xvEditResult += buf;       pDlg->m_xvEditResult += _T("\r\n"); } return 0; } "m_"はメンバ変数です。 以下がスレッド作成のソースになっています HANDLE hForth; unsigned int nForthID; hForth = (HANDLE)_beginthreadex(NULL, 0, ThSend , this, 0, &nForthID ); なぜ受信できないのか分からない状態です。 ではよろしくお願いします

  • スレッドの一時停止と再開について

    こんばんは。 VC++.NET2003でC言語にて、UDPソケットプログラミングを行っています。 A:送信端末 B:受信端末 とし、送信端末から受信端末へ各パケットにシーケンス番号を付加し1024Byteずつパケットを送信。受信端末は、送信端末からのパケットを受信するのですが、受信できなかったパケットがある場合、シーケンス番号を送信端末へ送信します。 これらから、送信端末は、送信と受信スレッドを持つ、マルチスレッドを行っています。 以下に送信端末のプログラムを示します。 main{  //受信スレッド生成  hTh = (HANDLE)_beginthreadex(NULL, 0, Sequence_Number, NULL, 0, &thID);  UDPSending(s_port,szServer);  //受信スレッド終了待ち  WaitForSingleObject( hTh, INFINITE );  CloseHandle(hTh); } //送信スレッド UDPSending(s_port,szServer){  //fread関数にて、1024Byteずつ区切る  while((n = fread(send_Buf,1,SEND_DATA_SIZE,fp)) != 0) {   UDPDataSend(s_port, szServer, send_Buff, n+mojisuu);  } } UDPDataSend(unsigned short s_port, char *szServer, char *send_Buff, int n){   sendtoにて受信端末へ送信 } //受信端末からの未受信シーケンス番号を受信(受信スレッド) unsigned __stdcall Sequence_Number(void *lpx){   recvfrom関数によりシーケンス番号を受信 } [付け加えたい機能] 送信スレッドにおいて100個のパケットを送信したら、一時的に送信スレッドを停止させ、受信スレッド内の処理を行い、受信スレッド内の処理が終えたら、再度、送信スレッドを再開させる方法はありますでしょうか? イメージでは・・・ S:送信スレッド R:受信スレッド とした場合、 S(100個パケット送信)→Sの休止→Rの処理→Rの処理が終えたら→Sの再開(再度100パケット送信)・・・・ の繰り返しです。 よろしくお願いします。

専門家に質問してみよう