2011-08-27 25 views
1

我有以下代码:代理所需的非阻塞套接字?

{         
    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。有谁能给我一个确认,我在这里的正确轨道上?或者,这种运动也可以用阻塞插座来完成吗?

Regards

回答

0

是的,你是在正确的轨道。使用非阻塞套接字传递它们的相关文件描述符来选择(请参阅FD_SET())。

这种方式选择将监视事件(读/写)在他们身上。

当选择返回时,您可以检查哪个fd发生了一个事件(查看FD_ISSET())并对其进行处理。

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

+0

非常感谢很多家伙,现在是我阅读那些实现它们的正确时间:) – user912877

1

您正处在正确的轨道上。

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

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

“epoll”是select和poll的高度可扩展版本。一个“选择”集合实际上被限制在一次只能监视一次的64-256个套接字,并且随着被监视的套接字数量的增加,它会发生一次全击。 “epoll”可以扩展到数千个并发的网络连接。

+0

OP没有具体提到目标操作系统的程序将运行。epoll很棒,但不幸的是它不是可移植的(特定于Linux)。其他系统也提供类似的选择(例如FreeBSD的kqueue和Solaris'/ dev/poll)。为epoll +1! –

0

是的,你必须使用其中一种机制。轮询是便携式和IMO最容易使用的。在这种情况下,您不必关闭屏蔽功能,前提是您使用了足够小的值作为RCVBUFSIZE(大约2k-10k应该合适)。非阻塞套接字的处理有点复杂,因为如果你发送的是EAGAIN,你不能再循环再试(可以,但是你不应该,因为它不必要地使用CPU)。

但我会推荐使用诸如libevent的包装。在这种情况下,struct bufferevent特别适合。当有新数据可用时,它将进行回调,并且您只需将它排队等待在另一个套接字上发送。

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