实现数据包超时 c++

发布于 2024-11-02 23:22:17 字数 3314 浏览 0 评论 0原文

对于一个计算机网络项目,我们正在用 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 循环来检查超时+时间戳是否大于允许的长整数大小,让我看看在比较之前clock_gettime是否会回落为零。知道这一点后,我检查了当前时间是否> (超时间隔 - (最大 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;
      }

For a computer networks project, we are writing an ftp server in c++ with different window protocols. We are having issues implementing a working timeout function. The gist of it is to set a timestamp to when a packet is transmitted, and if the "ack" isn't revived in a certain amount of time (say 2.5 milliseconds), retransmit the packet. We currently use the clock_gettime() function to get the current time and timestamp the packet.

Here is the while loop we are having issues with:

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;
    }
}  

Where ptimeout is the time that the packet was sent and connection_parameters->timeoutInterval is the timeout interval. The problem is that since ptimeout is a long integer representation of the time, sometimes it is a very large value (999715992 for example). This means that it will never be able to tell if the timeout has occurred, because the current time in nano seconds will be rest to 0 before the value gets large enough.

Has anyone else dealt with these timing issues in c++ and have a possible solution?

Thanks!

EDIT:

Thanks for the quick responses! I was able to get something figured out. Modifying to the while loop to check and see if the timeout+the timestamp would be larger than the allowed long intereger size let me see if the clock_gettime would get setback to zero before the comparison. Knowing this I checked if the current time > (timeout interval - (maximum long int val - time stamp)). This allows for a timeout of up to 1 second which should be plenty for the purposes of this problem. If anyone thinks they have a better solution, let me know! Thanks!
Here is the code for those interested:

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;
      }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

深海夜未眠 2024-11-09 23:22:17

您可能想将代码更改为:

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

只要确保没有任何整数溢出即可!例如,显式转换为 64 位整数可能是个好主意。

此外,您很可能希望超时至少比 2.5 毫秒大一个数量级,甚至可能更多。例如,您在操作系统中的时间片很可能约为 17 毫秒,更不用说网络延迟了。

you might want to change your code to say:

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

Just make sure you don't get any integer overflows! It's probably a good idea to explicitly cast to a 64 bit integer for instance.

Also, you most likely want a timeout at least one order of magnitude larger than 2.5 milliseconds, probably more. Your time slice in the operating system will most likely be somewhere around 17 milliseconds for instance, not to speak of network latencies.

半衾梦 2024-11-09 23:22:17

您需要查看 clock_gettime 填充的 timespec 对象的 tv_sectv_nsec 组件。 code>ptimeout 字段应该是 timespec 而不是整数。您必须编写函数来对 timespec 对象进行数学运算,我认为没有任何库存。

You need to look at both the tv_sec and tv_nsec components of the timespec object that clock_gettime fills in. Your ptimeout field should be a timespec rather than an integer. You'll have to write functions to do math on timespec objects, I don't think there's anything stock.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文