代理需要非阻塞套接字?

时间:2011-08-27 10:49:34

标签: c sockets tcp

我有以下代码:

 {                                
     send(dstSocket, rcvBuffer, recvMsgSize, 0);
     sndMsgSize = recv(dstSocket, sndBuffer, RCVBUFSIZE, 0);
     send(rcvSocket, sndBuffer, sndMsgSize, 0);           
     recvMsgSize = recv(rcvSocket, rcvBuffer, RCVBUFSIZE, 0);
 }

最终应该成为通用TCP代理的一部分。现在看来,它不能正常工作,因为recv()等待输入,所以数据只能以块的形式传输,具体取决于当前的位置。

我读到的是我需要类似“非阻塞套接字”和监视它们的机制。我发现的这种机制是Linux中的select,poll或epoll。谁能给我一个确认,我在这里正确的轨道?或者这个练习也可以用阻塞套接字完成吗?

问候

3 个答案:

答案 0 :(得分:1)

你走在正确的轨道上。

“select”和“poll”是系统调用,您可以在其中传递一个或多个套接字并阻塞(在特定的时间内),直到在其中一个套接字上接收到数据(或准备发送)。 / p>

“非阻塞套接字”是一个可以应用于套接字(或recv调用标志)的设置,这样如果您尝试调用recv但没有数据可用,则呼叫将立即返回。 “发送”存在类似的语义。您可以使用带有或不带上述select / poll方法的非阻塞套接字。使用非阻塞操作通常不是一个坏主意,以防您收到不存在的数据的信号。

“epoll”是一个高度可扩展的select和poll版本。 “选择”集实际上限制为64-256个套接字,用于一次监视,并且随着受监视套接字的数量增加,它会受到性能的影响。 “epoll”可以扩展到数千个同步网络连接。

答案 1 :(得分:0)

是的,你走在正确的轨道上。使用非阻塞套接字传递其相对文件描述符进行选择(参见FD_SET())。

这样select会监视它们的事件(读/写)。

当select返回时,您可以检查事件发生了哪个fd(查看FD_ISSET())并处理它。

您也可以在select上设置超时,即使没有发生事件,也会在该时间段后返回。

答案 2 :(得分:0)

是的,您必须使用其中一种机制。民意调查是可移植的,IMO是最容易使用的。在这种情况下,您不必关闭阻止,只要您为RCVBUFSIZE使用足够小的值(大约2k-10k应该是合适的)。非阻塞套接字处理起来要复杂一些,因为如果你在发送时得到EAGAIN,你就不能再循环再试一次(好吧你可以,但你不应该因为它不必要地使用CPU)。

但我建议使用像libevent这样的包装器。在这种情况下,struct bufferevent将特别有效。它会在新数据可用时进行回调,您只需将其排队等待在另一个套接字上发送。

试图找到一个bufferevent示例,但似乎有点短。无论如何,文档都在这里:http://monkey.org/~provos/libevent/doxygen-2.0.1/index.html