gpt4 book ai didi

c++ - Windows UDP 套接字 : recvfrom() fails with error 10054

转载 作者:可可西里 更新时间:2023-11-01 13:26:06 28 4
gpt4 key购买 nike


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

  • 当在我的套接字上调用 WSAPoll() 时,它总是返回我的套接字更新了所有可能的事件(对应于我给 pollfd 的每个事件),即使没有启动服务器。
  • 当调用 recvfrom() 并且没有服务器启动时,它返回 SOCKET_ERROR,错误代码为 10054(*)。
  • 当调用 recvfrom() 并启动服务器时,它会正常工作 - 阻塞直到它收到一些东西。
  • 无论我尝试连接到本地主机还是远程主机,行为都是一样的。

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

这是一个无法在我的计算机上运行的简单测试文件。

#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() 会返回此错误,我该如何解决?我想它来 self 的电脑。我尝试允许 ICMP 通过我的防火墙,但它没有改变任何东西,也许我做错了什么?

编辑:我通过忽略收到的任何“错误 10054”修复了我的主程序(此处未显示,因为它太大了)。现在它的工作方式与在 Unix 上一样。
尽管如此,它仍然不是真正的解决方案(忽略错误代码......嗯),如果有人知道为什么我在调用 sendto() 时收到“ICMP Port Unreachable”错误,我会很高兴听听它。

最佳答案

在 Windows 中,如果主机 A 使用 UDP 套接字并调用 sendto() 向主机 B 发送内容,但 B 未绑定(bind)任何端口,因此 B 收不到消息,并且然后主机 A 调用 recvfrom() 来接收一些消息,recvfrom() 将失败,并且 WSAGetLastError() 将返回 10054.

这是 Windows 的一个错误。如果 UDP 套接字在发送消息后收到 ICMP(port unreachable) 消息,则此错误将被存储,下次调用 recvfrom() 将返回此错误。

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

  1. 确保主机B已经绑定(bind)了你要发送到的端口。
  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

关于c++ - Windows UDP 套接字 : recvfrom() fails with error 10054,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34242622/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com