2010-05-26 29 views
1

嘿,我正在写一个udp客户端服务器,其中一个客户端等待来自服务器的数据包。但是我想限制这个等待一定的时间。客户端在某个时刻没有得到响应发出警报,基本上它出来了,并开始采取补救措施。那么它有什么可能的解决方案。我认为围绕recv写一个包装将起作用,但究竟该如何完成,我的意思是如何使recv升起警报你在此之后的时间限制。C,C++的中断机制

任何在这方面的帮助将不胜感激。

谢谢!

回答

6

如果你想用超时进行套接字通信,那么select是要走的路。

您基本上为各种事件设置了文件描述符数组,例如read-ready或write-able,然后在超时时调用select。如果其中一个事件有效,您将收到通知,您可以执行您的操作。

如果在超时之前没有发生任何事件,您仍会收到通知,并且可以采取您认为合适的任何补救措施。

查看here血淋淋的细节,扩展如下。

或者,你可以使用setsockopt与SO_RCVTIMEO:

struct timeval tv; 
tv.tv_sec = 5; 
tv.tv_used = 0; 
setsockopt (socket_id, SOL_SOCKET, SO_RCVTIMEO, 
    &tv, sizeof(struct timeval)); 

要详细了解select,您使用FD_ZEROFD_SET宏构建一组感兴趣文件描述符(fdsets)给你。您可以有三组,一组指示一个或多个fds是否有数据要读取,一个指示是否有一个或多个准备好写入,另一个指示错误。你可能不一定拥有全部三个,这取决于你的代码在做什么。

一旦你设置了fdsets,你就可以将它们连同fds的数量和超时时间一起传递给select,它编织它的魔法并返回给你。在执行此操作之前,请制作fdset的副本(FD_COPY)以供日后恢复。

返回时,出现错误,超时或与感兴趣的某个fds有关的事件。在后一种情况下,fdsets已被修改为仅为具有事件的那些设置了fds,并且您可以使用FD_ISSET来检测哪些fds。

然后,一旦处理了所有事件,请使用FD_COPY恢复原始fdsets(记住它们被修改为select),并再次调用select。继续,只要你需要。

请记住,从select返回的错误不一定是致命的。如果处理信号,您可以获得(在errnoEAGAIN暂时资源短缺或EINTR。对于第二种情况,您可以重新输入选择呼叫。首先,我会实施一个重试循环,以防只是暂时的事情。

+0

thansk for the reply。 – mawia 2010-05-26 09:46:54

+0

嗨! 有没有什么办法知道使用select,在哪个文件描述符操作发生?我的意思是,如果我们正在传递一个文件描述符,我们显然需要一些关于返回select的信息,关于哪个文件描述符在哪已经发生,因为它将有助于采取进一步的行动。 谢谢! – mawia 2010-05-26 15:45:36

+1

是的,描述符集是_modified_,以便只设置具有事件的位。如果错误(select errno),select'将返回-1,否则超时时返回0。如果你得到一个积极的ineteger,然后你使用FD_ISSET来检查集合中的每个文件描述符。只要确保在重新调用select之前重新初始化fd集。 – paxdiablo 2010-05-26 15:53:49

1

您可以使用select(...)并将非零超时作为最后一个参数。这是最便携的方式。

你也可以使用信号,但这不是可移植的,即使在有系统的系统上,它也可能不像你预期的那样工作。 (信号处理程序完成后,recv/select/whatever可能会重新启动,从而破坏整个目的。)

+0

感谢您的回复。 – mawia 2010-05-26 09:47:13