Reputation: 342
In this code:
// 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();
}
(note the MSG_WAITALL
flag in recv()
) everything works fine, expect for recv()
. WSAGetLastError()
returns WSAEOPNOTSUPP
.
MSDN states that
Note that if the underlying transport does not support MSG_WAITALL, or if the socket is in a non-blocking mode, then this call will fail with WSAEOPNOTSUPP. Also, if MSG_WAITALL is specified along with MSG_OOB, MSG_PEEK, or MSG_PARTIAL, then this call will fail with WSAEOPNOTSUPP. This flag is not supported on datagram sockets or message-oriented sockets.
But it doesn't look like I'm doing something from this list. Why my recv()
call doesn't work?
Upvotes: 1
Views: 3848
Reputation: 9
I can assure you that MSTCPIP most certainly supports MSG_WAITALL. You have been misinformed. On Win11 22H2, in the stack trace below which includes both user and kernel mode, notice the last arg to ws2_32!recv is 0x8. That is MSG_WAITALL!
00 fffff807`77b34d83 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : tcpip!TcpTlConnectionReceive
01 fffff807`77b33a9c : 00000000`00000000 ffffa786`4fb6fba0 00000000`00004020 ffffa786`4f8f31c0 : afd!AfdTLPostUserReceive+0xd3
02 fffff807`77b3358f : 00000000`00000400 000000b7`438ff778 a7865210`00000000 00000000`00004020 : afd!AfdBReceive+0x2cc
03 fffff807`77b4412d : ffffa786`4fbdc900 ffffa786`4f8f31c0 00000000`00000000 fffff887`00000400 : afd!AfdReceive+0x30f
04 fffff807`6f2934a5 : ffffa786`4fbdc900 00000000`00000002 00000000`00000001 fffff807`6f26a179 : afd!AfdDispatchDeviceControl+0x7d
05 fffff807`6f6cb210 : ffffa786`4fbdc900 00000000`00000002 ffffa786`4fbdc900 ffffa786`52113990 : nt!IofCallDriver+0x55
06 fffff807`6f6c97dc : 00000000`00000000 00000000`00012017 fffff887`6a867520 ffffa786`4fbdc900 : nt!IopSynchronousServiceTail+0x1d0
07 fffff807`6f6c7ab6 : 000000b7`438ff620 0000021e`ccceb430 00000000`00000000 00000000`00000000 : nt!IopXxxControlFile+0x72c
08 fffff807`6f433965 : ffffa786`50671080 fffff887`6a867520 000000b7`438ff5e8 000000b7`438ff298 : nt!NtDeviceIoControlFile+0x56
09 00007fff`8234ee54 : 00007fff`7ebd5925 00000000`00000000 00000000`000001f7 0000021e`ccceb430 : nt!KiSystemServiceCopyEnd+0x25
0a 00007fff`7ebd5925 : 00000000`00000000 00000000`000001f7 0000021e`ccceb430 00000000`00000000 : ntdll!NtDeviceIoControlFile+0x14
0b 00007fff`808b2417 : 00000000`000000ec 0000021e`cccd61c0 00000000`00000400 000000b7`438ff758 : mswsock!WSPRecv+0x2e5
0c 00007ff6`b2c0112e : 00000000`000000ec 00000000`00000000 00007fff`7fabf4a0 00000000`00000008 : WS2_32!recv+0x197
Upvotes: -1
Reputation: 595467
it doesn't look like I'm doing something from this list.
Yes, you are - the very first item on the list:
the underlying transport does not support MSG_WAITALL
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.
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.
Upvotes: 1