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



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

, (1) {选择(…Timeout = 5秒);//其他代码}

如果我在t = 2秒收到update,那么select()将返回并执行相应的语句。当下一个循环开始时,timeout将再次设置为5秒。但是,它应该是5 - 2 = 3秒。是否有一种方法来更新计时器与正确的时间?

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

根据select手册页:

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

因此,您只需重用timeout变量。只有当你真的超时时,你才会重置它的值。

正如警告所示,依赖于此行为会导致移植问题,因此,如果您依赖于此行为,请确保将其记录下来,以便在移植代码时做正确的事情。

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

也许你想使用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 );

最新更新