未连接的 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 不返回的主要内容,如果未能解决你的问题,请参考以下文章