未连接的 UDP 套接字上的 WSARecvFrom 不返回

Posted

技术标签:

【中文标题】未连接的 UDP 套接字上的 WSARecvFrom 不返回【英文标题】:WSARecvFrom on unconnected UDP socket does not return 【发布时间】:2011-03-28 17:48:59 【问题描述】:

我正在编写一个测试 UDP 网络服务的小程序。允许服务的实现为会话创建一个新的套接字并从那里响应客户端,此时客户端需要与该地址通信(类似于 TFTP)。

最小客户端无错误检查如下所示:

int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);

sockaddr_in destaddr =  ... ;
MSGBUF msg[] =  ... ;
DWORD sent;
WSASendTo(fd, msg, sizeof msg / sizeof *msg, &sent, 0, (sockaddr *)sa, sizeof sa, 0, 0);

char buffer[4096];
MSGBUF rcvmsg =  sizeof buffer, buffer ;
DWORD received;
sockaddr_storage sa;
socklen_t sa_len = sizeof sa;
DWORD flags = 0;
WSARecvFrom(fd, &rcvmsg, 1, &received, &flags, (sockaddr *)&sa, &sa_len, 0, 0);

如果服务器从初始消息发送到的相同地址和端口进行响应,则客户端可以正常工作,但是来自另一个端口的回复会被静默丢弃并且客户端在WSARecvFrom 中挂起。

将套接字显式绑定到 AF_INET, INADDR_ANY, 0 以强制分配本地端口,或者调用listen(fd, 5); 没有任何区别,正如预期的那样。

WSASendTo 中是否有任何隐式连接 UDP 套接字的内容,如果有,我应该怎么做才能避免这种情况?

【问题讨论】:

【参考方案1】:

UDP 没有连接。数据报被发送到端口和从端口发送;这是一种单向通信。

在我看来,您的服务器正在让自己被分配一个临时端口(即在 sockaddr_in 中将 0 作为端口传递),而不是使用特定端口。这行不通。

由于UDP没有连接的概念,每次发送数据时,都可能从不同的端口发送;第一次发送不会保留给定的端口,它只是从中发送一个数据报,然后放手。

您的服务器应该将自己绑定到特定端口。

【讨论】:

我知道这一切。我的问题是协议专门允许服务器这样做,只要它在原始地址和端口上联系客户端,因此客户端需要能够接收来自未知远程地址和端口的回复(这就是我在未连接的套接字上使用 WSARecvFrom 的原因——接受任何回复并了解回复的发送位置)。【参考方案2】:

嗯,这是防火墙问题。将应用程序添加到允许接收传入流量的程序列表中解决了该问题。

【讨论】:

以上是关于未连接的 UDP 套接字上的 WSARecvFrom 不返回的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中的 UDP 套接字编程中获取“传输端点未连接”

UDP的connect

UDP----socket通信

socket (套接字)

socket (套接字)

UDP打孔只能部分工作c#