2009-12-30 50 views
0

我有一个使用WSAASyncSelect将套接字置于异步模式的套接字库的问题。在异步模式下,套接字被置于非阻塞模式(在阻塞的任何操作上返回WSAWOULDBLOCK),并且将窗口消息发布到通知窗口,以通知应用程序套接字何时可以被读取,写入等。从异步套接字读取数据最佳

我的问题是这样的 - 接收FD_READ事件,我不知道有多少字节的尝试和recv时。如果我传递的缓冲区太小,那么winsock会自动发布另一个FD_READ事件,告诉我更多要读取的数据。如果数据以非常快的速度到达,可以使用FD_READ消息使消息队列饱和,并且由于只有当消息队列为空时才会发送WM_TIMER和WM_PAINT消息,这意味着如果应用程序接收到大量数据并使用异步缓冲区太小的套接字。

然后制作缓冲区有多大?我尝试使用ioctlsocket(FIONREAD)来获取要读取的字节数,并制作一个完全相同的缓冲区,但是,KB192599明确警告说,这种方法充满效率低下。

如何挑选足够大的缓冲区大小,但不是疯狂的大?

回答

1

就我所能解决的问题而言,使用setsockoptSO_RVCBUF选项设置的值是FIONREAD值的上限。因此,而不是调用ioctlsocket应该OK打电话getsockopt找出SO_RCVBUF设置,并使用为每个recv的(未遂)值。

基于对阿维亚德P.的回答您的意见,这听起来像这将解决您的问题。

(声明:我一直用自己FIONREAD但阅读链接到的知识库文章,我可能会被改变......之后)。

+0

我会用SO_RCVBUF作为最明智的缓冲区大小来使用。 – 2010-01-03 11:08:43

0

您可以设置缓冲区是一样大的,你可以在不影响性能,依靠TCP PUSH标志,使您的阅读填充缓冲区,如果发送方发送一个小的消息之前的回报。

的TCP PUSH标志被设置为逻辑消息边界(发送操作后,通常,除非明确地设置为false)。当接收端在TCP数据包上看到PUSH标志时,它将返回任何阻塞读取(或异步读取,无关紧要),直到PUSH点为止,在接收缓冲区中累积的任何内容。因此,如果你的发件人发送的是合理大小的信息,那么你可以,如果他不是,那么你限制了你的缓冲区大小,这样即使你全部读完了,你也不会对性能(主观)产生负面影响。

+0

我不是担心大的读回很快。在我的上下文中,我正在执行recv以响应FD_READ事件,所以它保证recv将立即返回一些信息,而不会立即尝试阻止它。我的问题是,如何计算recv缓冲区的大小,以便在一次recv调用中排除所有待处理数据。我可以做到1Mb,但摩尔定律暗示,即使这样做可能会有一天不会太远,但仍然是今天疯狂浪费资源。 – 2009-12-31 14:06:36

+0

只是好奇,你为什么要计算它?你不能一次循环一次吗? – 2009-12-31 14:33:14