1

我有一个非阻塞的 winsock 套接字,它正在recv循环中输入数据。

我注意到,当使用 putty 和原始套接字连接时,发送消息工作得很好。但是,当与此特定客户端交互时,数据包似乎没有触发成功的非MSG_PEEK调用recv. 我记得几年前有一个类似的问题,它最终不得不结束数据包\r或来自客户端的东西,在这种情况下这是不可能的,因为我无法修改客户端。

Wireshark 显示通过的数据包很好;但是,我的服务器程序运行不正常。

我将如何解决这个问题?

编辑:将缓冲区大小降低到例如 8 会导致在没有 MSG_PEEK 的情况下成功调用 recv。

接收调用:

iLen = recv(group->clpClients[cell]->_sock, // I normally call without MSG_PEEK
        group->clpClients[cell]->_cBuff, CAPS_CLIENT_BUFFER_SIZE, MSG_PEEK);
if(iLen != SOCKET_ERROR)
{
    ...

套接字是AF_INET和。SOCK_STREAMIPPROTO_TCP

4

4 回答 4

1

Microsoft 文档在几个地方指出MSG_PEEK应该完全避免,因为它效率低下且不准确。使用select(),WSAAsyncSelect()WSASelectEvent()代替检测套接字何时有可读取的数据,然后调用recv()WSARecv()实际读取它。

于 2012-06-29T19:46:42.337 回答
1

用于setsockopt设置TCP_NODELAY为 TRUE。

于 2012-07-15T21:28:12.317 回答
0

TCP 套接字是字节流,它不保留您的应用程序消息边界。一旦内核有东西给你,它就会从投票中返回。您必须收集接收到的字节,直到您有足够的能力来解码您需要解码的任何内容。

于 2012-06-29T19:07:33.017 回答
0

该解决方案最终是特定于实现的;我知道来自客户端的所有数据包的长度都可以被一定数量的字节整除。所以,我只是读取了这么多字节,直到缓冲区为空。

最大。在这种情况下,您一次可以接收的字节数必须小于最长消息的最大长度,并且必须是该长度的 GCF(最大公因数)。

这远不是一个永久的解决方案,但它现在有效。

于 2012-07-01T09:40:13.753 回答