大家好.
我正在尝试使用Windows套接字来发送和接收UDP数据包(在C++中).
它运作良好,直到三天前程序停止正常运行.
总结一下情况:
在我的套接字上调用WSAPoll()时,它总是返回我的套接字更新,即使没有服务器启动,也可以使用每个事件(对应于我给polveld的每个事件).
当调用recvfrom()并且没有启动服务器时,它返回SOCKET_ERROR,错误代码为10054(*).
当调用recvfrom()并启动服务器时,它可以正常工作 - 阻塞直到它收到一些东西.
无论我尝试连接到localhost还是远程主机,行为都是一样的.
(*)我调查了这个错误.在UDP中,这意味着存在ICMP问题.("在UDP数据报套接字上,此错误表示先前的发送操作导致ICMP端口无法访问消息.").
我确实在recvfrom()之前调用了sendto(),所以问题不在这里.
我试图放下我的防火墙,看它是否改变了什么,但事实并非如此.我还试图放下流经我电脑的每个网络.在这种状态下,我设法使程序工作了几分钟,但是当我启用网络时它再次停止工作.我试图重复这个过程,但它不再适用了.
我尝试使用visual studio(2015)和MinGW进行编译.
我也尝试了另一台计算机(在Windows 7下,我的Windows 8.1),无济于事.
这是一个简单的测试文件,在我的计算机上不起作用.
#undef _WIN32_WINNT #define _WIN32_WINNT 0x501 #include#include #include #include #include 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 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; }
两个问题:
为什么WSAPoll()总是返回一个更新的套接字,即使它没有与它进行任何交互?
为什么recvfrom()会返回此错误,我该如何解决?我想它来自我的电脑.我尝试通过我的防火墙允许ICMP,但它没有改变任何东西,也许我做错了什么?
编辑:我修改了我的主程序(这里没有显示,因为它太大了)只是忽略我收到的任何"错误10054".现在它的工作方式与在Unix上的工作方式相同.
不过,它实际上并不是一个解决方案(忽略错误代码...... meh)如果有人知道为什么我在调用时遇到"ICMP Port Unreachable"错误sendto()
,我很高兴听到它.
在Windows中,如果主机A使用UDP套接字并调用sendto()
将某些内容发送给主机B,但主机B没有绑定任何端口,则主机B不会接收到该消息,然后主机A recvfrom()
接收某些消息的调用recvfrom()
将失败,并且WSAGetLastError()
会回来的10054
。
这是Windows的错误。如果UDP套接字在发送消息后接收到ICMP(端口不可达)消息,则将存储此错误,下次调用recvfrom()
将返回此错误。
有两种方法可以解决此问题:
确保主机B已经绑定了要发送到的端口。
通过使用以下代码来禁用此错误:
#include
#include
#include
#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