Windows UDP sockets: recvfrom () error with error 10054


Welcome all.
I am trying to use Windows sockets to send and receive UDP packets (in C ++).
It worked well until three days ago when the program stopped behaving correctly.
To summarize the situation:

  • When WSAPoll () is called on my socket, it always returns my socket, updated with EVERY RESCUE (which corresponds to all the events that I gave pollfd), even if the server is not running.
  • When recvfrom () is called and the server starts, it does not return SOCKET_ERROR with error code 10054 (*).
  • When recvfrom () is called and the server starts, it works correctly - it blocks until it receives something.
  • The behavior is the same if I try to connect to a local host or a remote host.

(*) I investigated this error. In UDP, this means that there is a problem with ICMP. ("In the juice of a UDP datagram, this error indicates a previous send operation that resulted in an ICMP Port Unreachable message.").
I really call sendto () before recvfrom (), so the problem is not here.
I tried to set up my firewall to see if this had changed, but it is not. I also tried to suppress every network flowing through my computer. In this state, I managed to get the program to work for several minutes, but when I turned on the network, it stopped working again. I tried to repeat this process, but it will no longer work.
I tried compiling with both visual studio (2015) and MinGW.
I also tried on another computer (under Windows 7, I have Windows 8.1), to no avail.

Here is a simple test file that does not work on my computer.

#undef _WIN32_WINNT #define _WIN32_WINNT 0x501 #include <winsock2.h> #include <ws2tcpip.h> #include <stdio.h> #include <vector> #include <iostream> int main() { int clientSock; char buf[100]; int serverPort; /* Initializing WSA */ WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); /* I create my socket */ struct addrinfo specs; struct addrinfo *addr = new addrinfo; ZeroMemory(&specs, sizeof(specs)); specs.ai_family = AF_INET; specs.ai_socktype = SOCK_DGRAM; specs.ai_flags = 0; getaddrinfo("127.0.0.1", "2324", &specs, &addr); clientSock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); /* I get the server address */ struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); serverAddr.sin_port = htons(2324); int len = sizeof(struct sockaddr); /* I'll poll & recvfrom on my socket */ std::vector<pollfd> fds; pollfd fd; fd.fd = clientSock; fd.events = POLLRDNORM; fd.revents = -1; fds.push_back(fd); while(1) { memset(buf,0,sizeof(buf)); printf("\nClient--->: "); gets(buf); /* It UDP, so it doesn't matter if there is someone to receive the packet */ sendto(clientSock, buf, strlen(buf), 0, (sockaddr*)&serverAddr ,len); memset(buf,0,sizeof(buf)); int ret; /* Always returns "1" */ if ((ret = WSAPoll(fds.data(), 1, 0)) > 0) { std::cout << ret; /* Always returns "-1" */ std::cout << recvfrom(clientSock,buf,sizeof(buf),0, (sockaddr*)&serverAddr,&len) << std::endl; printf("\n--->From the server: "); printf("%s",buf); } } closesocket(clientSock); WSACleanup(); return 0; } 

Two questions:

  • Why does WSAPoll () always return an updated socket, even if there was no interaction with it?
  • Why is recvfrom () returning this error and how to fix it? I guess this is happening from my computer. I tried to allow ICMP through my firewall, but it didn’t change anything, maybe I did something wrong?

Edit: I fixed my main program (not shown here because it is too large), simply ignoring any "error 10054" I received. Now it works the same as on Unix.
However, this is not a solution (ignoring the error code ... meh), and if anyone knows why I get the "ICMP Port Unreachable" error message when calling sendto() , I would be happy to hear about it.

+5
source share
1 answer

On Windows, if host A uses a UDP socket and calls sendto() to send something to host B, but B does not bind any port so that B does not receive a message, then recvfrom() call to recvfrom() to receive some message recvfrom() will fail, and WSAGetLastError() will return 10054 .

This is a Windows error. If the UDP socket returns an ICMP message (message is not available) after sending the message, this error will be saved, and the next time the recvfrom() call will return this error.

There are two ways to solve this problem:

  • Make sure host B has already mapped the port you want to send.
  • Disable this error using the following code:
 #include <Winsock2.h> #include <Mstcpip.h> #include <stdio.h> #pragma comment(lib, "ws2_32.lib") #define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR, 12) BOOL bNewBehavior = FALSE; DWORD dwBytesReturned = 0; WSAIoctl(iSock, SIO_UDP_CONNRESET, &bNewBehavior, sizeof bNewBehavior, NULL, 0, &dwBytesReturned, NULL, NULL); 

Link: http://www.cnblogs.com/cnpirate/p/4059137.html

+3
source

Source: https://habr.com/ru/post/1237987/


All Articles