嘿,我正在写一个udp客户端服务器,其中一个客户端等待来自服务器的数据包。但是我想限制这个等待一定的时间。客户端在某个时刻没有得到响应发出警报,基本上它出来了,并开始采取补救措施。那么它有什么可能的解决方案。我认为围绕recv写一个包装将起作用,但究竟该如何完成,我的意思是如何使recv升起警报你在此之后的时间限制。C,C++的中断机制
任何在这方面的帮助将不胜感激。
谢谢!
嘿,我正在写一个udp客户端服务器,其中一个客户端等待来自服务器的数据包。但是我想限制这个等待一定的时间。客户端在某个时刻没有得到响应发出警报,基本上它出来了,并开始采取补救措施。那么它有什么可能的解决方案。我认为围绕recv写一个包装将起作用,但究竟该如何完成,我的意思是如何使recv升起警报你在此之后的时间限制。C,C++的中断机制
任何在这方面的帮助将不胜感激。
谢谢!
如果你想用超时进行套接字通信,那么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_ZERO
和FD_SET
宏构建一组感兴趣文件描述符(fdsets)给你。您可以有三组,一组指示一个或多个fds是否有数据要读取,一个指示是否有一个或多个准备好写入,另一个指示错误。你可能不一定拥有全部三个,这取决于你的代码在做什么。
一旦你设置了fdsets,你就可以将它们连同fds的数量和超时时间一起传递给select
,它编织它的魔法并返回给你。在执行此操作之前,请制作fdset的副本(FD_COPY
)以供日后恢复。
返回时,出现错误,超时或与感兴趣的某个fds有关的事件。在后一种情况下,fdsets已被修改为仅为具有事件的那些设置了fds,并且您可以使用FD_ISSET
来检测哪些fds。
然后,一旦处理了所有事件,请使用FD_COPY
恢复原始fdsets(记住它们被修改为select
),并再次调用select
。继续,只要你需要。
请记住,从select
返回的错误不一定是致命的。如果处理信号,您可以获得(在errno
)EAGAIN
暂时资源短缺或EINTR
。对于第二种情况,您可以重新输入选择呼叫。首先,我会实施一个重试循环,以防为只是暂时的事情。
您可以使用select(...)
并将非零超时作为最后一个参数。这是最便携的方式。
你也可以使用信号,但这不是可移植的,即使在有系统的系统上,它也可能不像你预期的那样工作。 (信号处理程序完成后,recv/select/whatever可能会重新启动,从而破坏整个目的。)
感谢您的回复。 – mawia 2010-05-26 09:47:13
thansk for the reply。 – mawia 2010-05-26 09:46:54
嗨! 有没有什么办法知道使用select,在哪个文件描述符操作发生?我的意思是,如果我们正在传递一个文件描述符,我们显然需要一些关于返回select的信息,关于哪个文件描述符在哪已经发生,因为它将有助于采取进一步的行动。 谢谢! – mawia 2010-05-26 15:45:36
是的,描述符集是_modified_,以便只设置具有事件的位。如果错误(select errno),select'将返回-1,否则超时时返回0。如果你得到一个积极的ineteger,然后你使用FD_ISSET来检查集合中的每个文件描述符。只要确保在重新调用select之前重新初始化fd集。 – paxdiablo 2010-05-26 15:53:49