トップページ > 過去ログ > 記事閲覧
データ通信について
名前:まるお 日時: 2011/10/12 09:46

現在TCP/IPでのデータ通信プログラムを作成しています。 フレームレートは60fpsでデータの送受信を行っているのですが、 受信が10回に1回程度しか行われず、 行われた時は未受信だったデータがまとめて受信される ようになっているみたいでした。 送信速度の問題や、受信の速度・処理の関係上 これは仕様としてしかたがないことなのでしょうか? 仕様であるなら、対策としてはUDPを使ったり、 補間を行う程度の事しか考えつきませんでした。 データ通信に関してほとんど初心者なので、ここまで成功しないものかと困っています。 よろしければ理由や対策などを教えていただければと思います。 よろしくお願いします。

Page: 1 |

Re: データ通信について ( No.1 )
名前:いっち 日時:2011/10/13 23:51

> フレームレートは60fpsでデータの送受信を行っているのですが、 > 受信が10回に1回程度しか行われず、 > 行われた時は未受信だったデータがまとめて受信される > ようになっているみたいでした。 そういうこともあるかな・・・という気はしますが、 検証に使用したコードをご提供頂けますか?
Re: データ通信について ( No.2 )
名前:管理人 日時:2011/10/16 22:04

私もデータ通信に関してはそんなに詳しくありませんが分かる範囲で・・・ 60fpsで毎フレームデータを送信したとしても、 相手側にも毎フレームデータが受信される保証はありません ( 通信環境によっては60fpsで受信される可能性もありますが、  それは TCP/IP の仕様で保証されているものではありません ) なので、データ通信を行うゲームではデータ通信が遅延したり 滞ったりした場合のことを考慮しておく必要があります UDP は TCP/IP より高速に相手にデータを届けることができますが TCP/IP と違い「送信したデータが相手に届かない」ことがありますので 注意してください( 通信品質が悪いルートを経由するとそれだけ 届かない可能性が高くなります )
Re: データ通信について ( No.3 )
名前:まるお 日時:2011/10/17 17:38

>>管理人さん なるほど、通信環境などによって程度の差はあれ 遅延は起こり得るもので、UDPにしても信頼性は下がるので それに対する対策を講じる必要があるということですね。 >>いっちさん 以下のような形でデータの送受信を行っています。 メイン部分については、後は初期設定と終了設定、変数の定義、画像ハンドルのロード程度しか行っていません。 CurrentPositions関数ではx座標の計算を行い、構造体に格納しています。 検証には送られてきたデータと送ったデータを fprintfでファイルに書き込んで、値がどのようになっているかを検証しました。 煩雑なプログラムで大変申し訳ないのですが、 不自然な点や問題がありそうな点があればご指摘いただきたく思います。 よろしくお願いいたします。 ********************************メイン部分の送受信の関数を呼び出してる部分************************************ c_state = NetWorkConnect(network); if(c_state == 1){ ///////////////////////////クライアント/////////////////////////////// while( ProcessMessage()==0 && ClearDrawScreen()==0 && CheckHitKey( KEY_INPUT_ESCAPE )!=1){ ReceiveCurrentData(&pos); // 描画先を指定する SetDrawScreen( DX_SCREEN_BACK ) ; // 画面をクリア ClearDrawScreen() ; DrawGraph( pos.x,0, GraphHandle , TRUE ) ; // 裏画面の内容を表画面に反映 ScreenFlip() ; // 新たに切断されたネットワークハンドルを得る LostHandle = GetLostNetWork() ; // 切断された接続が今まで通信してた相手だった場合ループを抜ける if( LostHandle == NetHandle[0] ) break ; } } else if(c_state==2){ //////////////////////////////サーバー/////////////////////////////// while( ProcessMessage()==0 && ClearDrawScreen()==0 && CheckHitKey( KEY_INPUT_ESCAPE )!=1){ CurrentPositions(motionT,&pos); SendCurrentData(&pos); // 描画先を指定する SetDrawScreen( DX_SCREEN_BACK ) ; // 画面をクリア ClearDrawScreen() ; DrawGraph( pos.x,0, GraphHandle , TRUE ) ; // 裏画面の内容を表画面に反映 ScreenFlip() ; // 新たに切断されたネットワークハンドルを得る LostHandle = GetLostNetWork() ; // 切断された接続が今まで通信してた相手だった場合ループを抜ける if( LostHandle == NetHandle[0] ) break ; } } if(c_state==1){ NetWorkConnect(N_LOST); } // 接続を断つ if(c_state==2){ NetWorkConnect(N_CLOSE); } ********************************************************************************************************* ***********************************ネットワーク通信の接続確立部分********************************************* int NetWorkConnect(int mode){ char StrBuf[ 256 ] ; // データバッファ int DataLength ; // 受信データ量保存用変数 int i=0; int counter=0; int ipCounter=0; int now; IPDATA Ip[10] ; // 接続先IPアドレスデータ if(mode==SERVER){ //////-- 接続待ち側プログラム--////// DrawString( 0 , 16 , "サーバーだよ" , GetColor( 255 , 255 , 255 ) ) ; // 接続してくるのを待つ状態にする PreparationListenNetWork( 9850 ) ; for(i=0;i<10;i++){ // 接続してくるかESCキーが押されるまでループ NetHandle[i] = -1 ; } i=0; while( !ProcessMessage() && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) { // 新しい接続があったらそのネットワークハンドルを得る NetHandle[i] = GetNewAcceptNetWork() ; if(NetHandle[i]!=-1) { i++; counter=0; } counter++; WaitTimer(1); if((counter>15000 && NetHandle[0]!=-1) || i>10) { break ; } } // 接続されていたら次に進む if( NetHandle[0] != -1 ) { // 接続の受付を終了する StopListenNetWork() ; for(i=0;i<10;i++){ if(NetHandle[i]==-1) break; // 接続してきたマシンのIPアドレスを得る GetNetWorkIP( NetHandle[i] , &Ip[i] ) ; } i=0; while(i<10 || NetHandle[i]!=-1){ NetWorkSend( NetHandle[i] , "繋がったか〜!?" , 17 ) ; i++; } // データがくるのを待つ while( !ProcessMessage() ) { // 取得していない受信データ量を得る DataLength = GetNetWorkDataLength( NetHandle[0] ) ; // 取得してない受信データ量が0じゃない場合はループを抜ける if( DataLength != 0 ) break ; } // データ受信 NetWorkRecv( NetHandle[0] , StrBuf , DataLength ) ; // データをバッファに取得 // 受信したデータを描画 DrawString( 0 , 0 , StrBuf , GetColor( 255 , 255 , 255 ) ) ; return 2; } } else if(mode==CLIENT){ //////-- 接続側プログラム--////// DrawString( 0 , 16 , "クライアントだよ" , GetColor( 255 , 255 , 255 ) ) ; // IPアドレスを設定( ここにある4つのIP値は仮です ) Ip[0].d1 = 192 ; Ip[0].d2 = 168 ; Ip[0].d3 = 11 ; Ip[0].d4 = 0 ; while(!ProcessMessage() && (CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )){ // 通信を確立 NetHandle[0] = ConnectNetWork( Ip[0], 9850 ) ; if( NetHandle[0]>=0 ) break; Ip[0].d4++; if(Ip[0].d4==256)break; } // 確立が成功した場合のみ中の処理をする if( NetHandle[0] != -1 ) { // データが送られて来るまで待つ while( !ProcessMessage() ) { // 取得していない受信データ量を得る DataLength = GetNetWorkDataLength( NetHandle[0] ) ; // 取得してない受信データ量が0じゃない場合はループを抜ける if( DataLength != 0 ) break ; } // データ受信 NetWorkRecv( NetHandle[0] , StrBuf , DataLength ); // データをバッファに取得 // 受信したデータを描画 DrawString( 0 , 0 , StrBuf , GetColor( 255 , 255 , 255 ) ) ; // 受信成功のデータを送信 NetWorkSend( NetHandle[0] , "繋がったぞ〜!!" , 17 ) ; return 1; } } if(mode==N_CLOSE){ i=0; while(NetHandle[i]!=-1){ CloseNetWork( NetHandle[i] ) ; i++; } } else if(mode=N_LOST){ // 切断確認表示 DrawString( 0 , 16 , "切断しました" , GetColor( 255 , 255 , 255 ) ) ; } return -1; } ********************************************************************************************************* **************************************データの送受信の関数************************************************ void SendCurrentData(Posdata *pPos) { int i; char senddata[1024]; sprintf(senddata,"%f",pPos->x); i=0; while(i<10 && NetHandle[i] != -1){ NetWorkSend( NetHandle[i] , senddata , lstrlen(senddata)+1 ); i++; } } void ReceiveCurrentData(Posdata *pPos) { int DataLength2=0; char recdata[1024]; // 取得していない受信データ量が0以外のときはループから抜ける if( GetNetWorkDataLength( NetHandle[0] ) != 0 ){ // データ受信 DataLength2 = GetNetWorkDataLength( NetHandle[0] ) ; // データの量を取得 } // 取得してない受信データ量が0じゃない場合 if( DataLength2 != 0 ) { // データ受信 NetWorkRecv( NetHandle[0] , recdata , DataLength2 ) ; // データをバッファに取得 pPos->x=(float)atof(recdata); } DataLength2=0; } *********************************************************************************************************
Re: データ通信について ( No.4 )
名前:いっち 日時:2011/10/18 18:11

コードを拝見した範囲では特にこれといった事は無いと思います。 テスト環境(と、できればpingの結果)を教えてください。 サーバとクライアントを同一PC上で動作させてもその様な結果になるのでしょうか?
Re: データ通信について ( No.5 )
名前:まるお 日時:2011/10/19 10:22

テスト環境はローカルで 送信側がWindows7のCorei7 受信側がWindowsXPのXeonです。 線は一応有線で繋がっています。 Pingの結果については以下のようになりました。 ************************ C:\Users\xxx>PING 192.168.11.8 192.168.11.8 に ping を送信しています 32 バイトのデータ: 192.168.11.8 からの応答: バイト数 =32 時間 <1ms TTL=128 192.168.11.8 からの応答: バイト数 =32 時間 <1ms TTL=128 192.168.11.8 からの応答: バイト数 =32 時間 <1ms TTL=128 192.168.11.8 からの応答: バイト数 =32 時間 <1ms TTL=128 192.168.11.8 の ping 統計: パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、 ラウンド トリップの概算時間 (ミリ秒): 最小 = 0ms、最大 = 0ms、平均 = 0ms ************************ 同一PC上で動作させた場合はそういった現象は見られず、 せいぜい2,3回に1回受信側でデータの受け取りが行われていない程度でした。 受信していないときの状況なのですが、 実際に受信の関数には入ってるみたいで、DateLengthが0となっており、 データが届いてないと処理されているみたいでした。
Re: データ通信について ( No.6 )
名前:いっち 日時:2011/10/19 20:44

回答ありがとうございます。 しかし、お話を聞く限り特にコードや環境の問題という感じではないようです。 私の手元の環境でも似たような結果でした。 お役に立てずすみません。
Re: データ通信について ( No.7 )
名前:まるお(解決) 日時:2011/10/20 13:33

やはり原因の特定は難しそうですね。 UDPや補間を使ったりして、色々工夫してみます。 丁寧な御対応ありがとうございました。

Page: 1 |