我有以下代码:
{
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。谁能给我一个确认,我在这里正确的轨道?或者这个练习也可以用阻塞套接字完成吗?
问候
答案 0 :(得分:1)
你走在正确的轨道上。
“select”和“poll”是系统调用,您可以在其中传递一个或多个套接字并阻塞(在特定的时间内),直到在其中一个套接字上接收到数据(或准备发送)。 / p>
“非阻塞套接字”是一个可以应用于套接字(或recv调用标志)的设置,这样如果您尝试调用recv但没有数据可用,则呼叫将立即返回。 “发送”存在类似的语义。您可以使用带有或不带上述select / poll方法的非阻塞套接字。使用非阻塞操作通常不是一个坏主意,以防您收到不存在的数据的信号。
答案 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