繁体   English   中英

在套接字编程的select()中重新启动计时器

[英]Restart the timer in select() of socket programming

我想使用select()从其他服务器接收更新,并定期发送消息。 考虑以下设置:

while(1){select(...超时= 5秒); //其他代码}

如果我在t = 2秒时收到更新,则select()将返回并执行相应的语句。 下一个循环开始时,超时将再次设置为5秒。 但是,应为5-2 = 3秒。 有没有办法用正确的时间更新计时器?

我考虑过要在select()之前手动启动一个计时器,但是此计时器可能与select()中使用的计时器不同步。 并会引起其他潜在的问题。

根据select手册页

在Linux上, select()修改超时以反映未休眠的时间; 大多数其他实现则不这样做。 (POSIX.1-2001允许任何一种行为。)

因此,您只需重复使用timeout变量即可。 仅在真正超时时才重置其值。

如警告所示,依赖此行为会导致移植问题,因此,如果您依赖此行为,请确保对其进行记录,以便在移植代码时完成正确的操作。

只需在调用select()之前记住变量中的time() ,然后在select()返回时获取另一个time() ,然后在下一个while(1)迭代中不使用5 ,而是使用5 - difference_between_times作为超时值。

也许您想使用new_timeout = 5 - difference_between_times % 5 ,这样,如果select返回后操作花费的时间超过5秒...您仍将timeout设置为5秒间隔。

您可能不应该使用秒,而应使用更精细的时间单位。 并思考以上是否是您真正想要的行为(带模)。 也许当difference_between_times > 5 ,您应该只等待5秒。 随心所欲,但您明白了。

当您的应用变得更加复杂时,您可能会遇到多个计时器,它们具有不同的超时间隔。 我们的确是。 这是我们的处理方式。

每个计时器都有一个计时器对象,该计时器对象的time_t为计时器何时到期。 我们将所有计时器存储在堆数据结构中,因此最快到期的计时器位于堆的根目录。 在执行select()之前,我们获取堆的根,然后从计时器的到期时间中减去当前时间,并使用该增量作为select()调用的超时。

Timer * t = heap->Root();
time_t now = time(0);
timeval tv;
tv.tv_sec = t->when - now;
tv.tv_usec = 0;
select( ... & tv );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM