我有一个非阻塞的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_STREAM
和IPPROTO_TCP
。
答案 0 :(得分:1)
Microsoft文档在几个地方声明MSG_PEEK
应该完全避免,因为它效率低且不准确。使用select()
,WSAAsyncSelect()
或WSASelectEvent()
来检测套接字何时可以读取数据,然后调用recv()
到WSARecv()
以实际读取它。< / p>
答案 1 :(得分:0)
解决方案最终成为特定于实施的;我知道来自客户端的所有数据包的长度可以被一定量的字节整除。所以,我只读取了那个字节数,直到缓冲区为空。
最大在这种情况下,您一次可以接收的字节数必须小于最长消息的最大长度,并且必须是该长度的GCF(最大公因数)。
这远非一个永久的解决方案,但它现在有效。
答案 2 :(得分:0)
使用setsockopt
将TCP_NODELAY
设置为TRUE。
答案 3 :(得分:-1)
TCP套接字是 bytes 的流,它不保留您的应用程序消息边界。只要内核有某些东西给你,它就会从民意调查中返回。您必须收集接收的字节,直到您有足够的数据来解码您需要解码的内容。