recv()与MSG_PEEK显示完整的消息,但正常返回'将阻止'

时间:2012-06-29 18:05:07

标签: c++ winsock recv peek

我有一个非阻塞的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_INETSOCK_STREAMIPPROTO_TCP

4 个答案:

答案 0 :(得分:1)

Microsoft文档在几个地方声明MSG_PEEK应该完全避免,因为它效率低且不准确。使用select()WSAAsyncSelect()WSASelectEvent()来检测套接字何时可以读取数据,然后调用recv()WSARecv()以实际读取它。< / p>

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

使用setsockoptTCP_NODELAY设置为TRUE。

答案 3 :(得分:-1)

TCP套接字是 bytes 的流,它不保留您的应用程序消息边界。只要内核有某些东西给你,它就会从民意调查中返回。您必须收集接收的字节,直到您有足够的数据来解码您需要解码的内容。

相关问题