2

コンピュータネットワークプロジェクトでは、さまざまなウィンドウプロトコルを使用してc++でftpサーバーを作成しています。動作するタイムアウト関数の実装に問題があります。その要点は、パケットが送信されるときにタイムスタンプを設定することです。「ack」が特定の時間(たとえば、2.5ミリ秒)以内に復活しない場合は、パケットを再送信します。現在、この関数を使用してclock_gettime()、パケットの現在の時刻とタイムスタンプを取得しています。

問題が発生しているwhileループは次のとおりです。

while(packet_sync_array[prev].recieved ==0 && t==0)
{
    clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&timeout2);
    currtime = timeout2.tv_nsec;
    cout << "Is currtime: "<<currtime<< " - ptimeout " << ptimeout 
         << " = " << (currtime - ptimeout) << " > " 
         << (connection_parameters->timeoutInterval)*1000 << "?" << endl;

    if((currtime - ptimeout)>((connection_parameters->timeoutInterval)*1000))
    {
        t = 1;
        cout << "Prev PACKET TIMEDOUT" << endl;
        cout << "Is currtime: "<<currtime<< " - ptimeout " << ptimeout 
             << " = " << (currtime - ptimeout) << " > " 
             << (connection_parameters->timeoutInterval)*1000 << "?" << endl;
    }
}  

はパケットptimeoutが送信された時間であり、connection_parameters->timeoutIntervalはタイムアウト間隔です。問題は、ptimeoutが時間の長整数表現であるため、非常に大きな値になる場合があることです(たとえば、999715992)。これは、値が十分に大きくなる前にナノ秒単位の現在の時間が0にとどまるため、タイムアウトが発生したかどうかを判断できないことを意味します。

他の誰かがc++でこれらのタイミングの問題に対処し、可能な解決策を持っていますか?

ありがとう!

編集:

迅速な対応ありがとうございます!私は何かを理解することができました。whileループを変更して、タイムアウト+タイムスタンプが許可されている長いinteregerサイズよりも大きいかどうかを確認し、比較の前にclock_gettimeがゼロに戻るかどうかを確認します。これを知って、現在の時刻>(タイムアウト間隔-(maximum long int val-タイムスタンプ))かどうかを確認しました。これにより、最大1秒のタイムアウトが可能になります。これは、この問題の目的には十分なはずです。誰かが彼らがより良い解決策を持っていると思うなら、私に知らせてください!ありがとう!興味のある人のためのコードは次のとおりです。

if(((999999998-ptimeout)< (connection_parameters->timeoutInterval)*1000)&&(currtime - ptimeout)<0){
          if(currtime > (((connection_parameters->timeoutInterval)*1000)-(999999998-ptimeout))){
              t = 1;
              cout << "this wrapped since " << currtime << " + " << (connection_parameters->timeoutInterval)*1000 << "is bigger than 999999999 and then timed out" << endl;
              cout << "curr time " << currtime << "is bigger than" << endl;
              cout << (connection_parameters->timeoutInterval)*1000 << endl;
              cout << "-" << endl;
              cout << (999999998-ptimeout) << endl;
              cout << "---------------------------" << endl;
              cout << (((connection_parameters->timeoutInterval)*1000)-(999999998-ptimeout)) << endl;
              cout << "Prev PACKET TIMEDOUT" << endl;
              cout << "Is currtime: "<<currtime<< " - ptimeout " << ptimeout << " = " << (currtime - ptimeout) << " > " << (connection_parameters->timeoutInterval)*1000 << "?" << endl;
          }
      }
      else if((currtime - ptimeout)>((connection_parameters->timeoutInterval)*1000)){
       t = 1;
       cout << "Prev PACKET TIMEDOUT" << endl;
       cout << "Is currtime: "<<currtime<< " - ptimeout " << ptimeout << " = " << (currtime - ptimeout) << " > " << (connection_parameters->timeoutInterval)*1000 << "?" << endl;
      }
4

2 に答える 2

3

次のようにコードを変更することをお勧めします。

// time in microseconds
currtime = timeout2.tv_sec * 1000000 + timeout2.tv_nsec / 1000;

整数のオーバーフローが発生しないように注意してください。たとえば、64ビット整数に明示的にキャストすることはおそらく良い考えです。

また、2.5ミリ秒より少なくとも1桁大きい、おそらくそれ以上のタイムアウトが必要になる可能性があります。オペレーティングシステムのタイムスライスは、ネットワークの遅延は言うまでもなく、たとえば約17ミリ秒になる可能性があります。

于 2011-04-20T02:34:22.910 に答える
1

入力するオブジェクトのtv_sectv_nsecコンポーネントの両方を確認する必要があります。フィールドは整数ではなく、である必要があります。オブジェクトに対して数学を行うための関数を作成する必要があります。在庫はないと思います。timespecclock_gettimeptimeouttimespectimespec

于 2011-04-20T02:16:56.143 に答える