本文介绍了Winsock2 - 如何打开允许 ​​recv() 和 MSG_WAITALL 的 TCP 套接字?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这段代码中:

// error checking is omitted

// init Winsock2
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);

// connect to server
struct addrinfo *res = NULL, *ptr = NULL, hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

getaddrinfo(server_ip, "9999", &hints, &res);
SOCKET client_socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);

connect(client_socket, res->ai_addr, (int)res->ai_addrlen);

freeaddrinfo(res);
res = NULL;

// read the data
unsinged int size1;
if (recv(client_socket, (char*)&size1, sizeof(int), MSG_WAITALL) == SOCKET_ERROR)
{
    return WSAGetLastError();
}

(注意 recv() 中的 MSG_WAITALL 标志)一切正常,除了 recv().WSAGetLastError() 返回 WSAEOPNOTSUPP.
MSDN 指出

(note the MSG_WAITALL flag in recv()) everything works fine, expect for recv(). WSAGetLastError() returns WSAEOPNOTSUPP.
MSDN states that

请注意,如果底层传输不支持 MSG_WAITALL,或者套接字处于非阻塞模式,则此调用将失败并显示 WSAEOPNOTSUPP.此外,如果 MSG_WAITALL 与 MSG_OOB、MSG_PEEK 或 MSG_PARTIAL 一起指定,则此调用将失败并显示 WSAEOPNOTSUPP.数据报套接字或面向消息的套接字不支持此标志.

但看起来我并没有从这个列表中做一些事情.为什么我的 recv() 调用不起作用?

But it doesn't look like I'm doing something from this list. Why my recv() call doesn't work?

推荐答案

是的,您是 - 列表中的第一项:

Yes, you are - the very first item on the list:

底层传输不支持 MSG_WAITALL

Microsoft 的默认 TCP 传输提供程序不支持 MSG_WAITALL.recv() 和一般的 Winsock 不仅限于 Microsoft 的 TCP 提供程序.它支持第 3 方提供商,以及提供商支持的任何传输协议 - TCP、UDP、IPX、ICMP、RAW 等.

Microsoft's default TCP transport provider does not support MSG_WAITALL. recv(), and Winsock in general, is not limited to just Microsoft's TCP provider. It supports 3rd party providers, and any transport protocols that the provider supports - TCP, UDP, IPX, ICMP, RAW, etc.

当使用微软的 TCP 时,如果你想让 recv() 等到所有请求的 TCP 数据都被接收到,你必须将套接字设置为阻塞模式(它的默认模式)然后将 recv()flags 参数设置为 0.但即使这样也不能保证,recv() 返回的字节数可能少于请求的字节数,所以你应该准备好在循环中调用 recv() 直到实际接收到所有预期的字节.

When using Microsoft's TCP, if you want recv() to wait until all of the requested TCP data has been received, you have to set the socket to blocking mode (its default mode) and then set the flags parameter of recv() to 0. But even that is not guaranteed, recv() can return with fewer bytes than requested, so you should be prepared to call recv() in a loop until all intended bytes have actually been received.

这篇关于Winsock2 - 如何打开允许 ​​recv() 和 MSG_WAITALL 的 TCP 套接字?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 21:38