本文介绍了Windows UDP 套接字:recvfrom() 失败,错误 10054的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


大家好.
我正在尝试使用 Windows 套接字来发送和接收 UDP 数据包(在 C++ 中).
它运行良好,直到三天前程序停止正常运行.
总结一下情况:


Hello everyone.
I'm 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 properly.
To summarize the situation:

  • 在我的套接字上调用 WSAPoll() 时,它总是返回我的套接字更新为所有可能的事件(对应于我给 pollfd 的每个事件),即使没有启动服务器.
  • 当调用 recvfrom() 并且没有启动服务器时,它返回 SOCKET_ERROR,错误代码为 10054(*).
  • 当调用 recvfrom() 并启动服务器时,它会正常工作 - 阻塞直到它收到一些东西.
  • 无论我尝试连接到本地主机还是远程主机,行为都是相同的.
  • When calling WSAPoll() on my socket, it always returns my socket updated with EVERY revents possible (corresponding to every events I gave the pollfd), even if there is no server launched.
  • When calling recvfrom() and no server is launched, it returns SOCKET_ERROR with error code 10054(*).
  • When calling recvfrom() and a server is launched, it works properly - blocks until it receives something.
  • The behavior is the same whether I try to connect to localhost or to a distant host.

(*) 我调查了这个错误.在 UDP 中,这意味着存在 ICMP 问题.(在 UDP 数据报套接字上,此错误表明先前的发送操作导致 ICMP 端口无法访问消息.").
我确实在 recvfrom() 之前调用了 sendto(),所以问题不在这里.
我试图关闭我的防火墙,看看它是否有任何改变,但它没有.我还尝试关闭流经我 PC 的每个网络.在这种状态下,我设法让程序运行了几分钟,但是当我启用网络时,它又停止了工作.我试图重复这个过程,但它不再起作用了.
我尝试使用 Visual Studio (2015) 和 MinGW 进行编译.
我也在另一台计算机上尝试过(在 Windows 7 下,我的是 Windows 8.1),但无济于事.

这是一个简单的测试文件,在我的电脑上不起作用.

(*) I investigated this error. In UDP, it means that there is an ICMP problem. ("On a UDP-datagram socket this error indicates a previous send operation resulted in an ICMP Port Unreachable message.").
I indeed call sendto() before recvfrom(), so the problem's not here.
I tried to put down my firewall to see if it changed anything, but it didn't. I also tried to put down every network flowing through my PC. In this state I managed to get the program to work for a few minutes, but when I enabled the networks it stopped working again. I tried to repeat the process but it would not work anymore.
I tried compiling with both visual studio (2015) and MinGW.
I tried on another computer too (under Windows 7, mine has Windows 8.1), to no avail.

Here is a simple test file which 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's 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's 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;
}

两个问题:

  1. 为什么 WSAPoll() 总是返回一个更新的套接字,即使没有任何交互?
  2. 为什么 recvfrom() 会返回这个错误,我该如何解决?我想它来自我的电脑.我尝试允许 ICMP 通过我的防火墙,但它没有改变任何东西,也许我做错了什么?
  1. Why does WSAPoll() always returns an updated socket, even if there wasn't any interaction with it ?
  2. Why does recvfrom() return this error and how can I fix it ? I suppose it comes from my computer. I tried allowing ICMP through my firewall but it didn't change anything, maybe I did something wrong ?

我通过忽略收到的任何错误 10054"来修复我的主程序(此处未显示,因为它太大了).现在它的工作方式与在 Unix 上的工作方式相同.
尽管如此,这并不是一个真正的解决方案(忽略错误代码......meh),如果有人知道为什么我在调用 sendto() 时收到ICMP Port Unreachable"错误,我会很高兴去听听.

I fixed my main program (not shown here because it is way too large) by just ignoring any "error 10054" I received. Now it works the same way it does on Unix.
Still, it is not really a solution (ignoring an error code... meh) and if anyone knows why I get the "ICMP Port Unreachable" error when calling sendto(), I'd be glad to hear about it.

推荐答案

在 Windows 中,如果主机 A 使用 UDP 套接字并调用 sendto() 向主机 B 发送一些东西,但 B 没有绑定任意端口,使 B 收不到消息,然后主机 A 调用 recvfrom() 接收一些消息,recvfrom() 会失败,WSAGetLastError() 将返回 10054.

In Windows, if host A use UDP socket and call sendto() to send something to host B, but B doesn't bind any port so that B doesn't receive the message, and then host A call recvfrom() to receive some message, recvfrom() will failed, and WSAGetLastError() will return 10054.

这是Windows的一个错误.如果UDP socket在发送消息后接收ICMP(port unreachable)消息,这个错误会被存储,下次调用recvfrom()会返回这个错误.

It's a bug of Windows. If UDP socket recv a ICMP(port unreachable) message after send a message, this error will be stored, and next time call recvfrom() will return this error.

有两种方法可以解决这个问题:

There are 2 ways to solve this problem:

  1. 确保主机 B 已经绑定了您要发送到的端口.
  2. 使用以下代码禁用此错误:
#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);

参考:http://www.cnblogs.com/cnpirate/p/4059137.html

这篇关于Windows UDP 套接字:recvfrom() 失败,错误 10054的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 05:46