未连接的 UDP 套接字上的 WSARecvFrom 不返回
我正在编写一个测试 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 套接字的内容,如果是,我应该怎么做才能避免这种情况?
I am writing a small program that tests an UDP network service. The implementation of the service is allowed to create a new socket for the session and respond to the client from there, at which point the client is then required to talk to this address (similar to TFTP).
Minimal client sans error checking looks like this:
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);
The client works fine if the server responds from the same address and port that the initial message was sent to, however replies from another port are silently discarded and the client hangs in WSARecvFrom
.
Explicitly binding the socket to { AF_INET, INADDR_ANY, 0 }
to force assignment of a local port, or invoking listen(fd, 5);
makes no difference, as expected.
Is there anything in WSASendTo that implicitly connects an UDP socket, and if so, what should I do to avoid this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
UDP 没有连接。数据报从端口发送到端口;这是一种单向通信。
在我看来,您的服务器正在为自己分配一个临时端口(即将 0 作为
sockaddr_in
中的端口传递),而不是使用特定端口。这行不通。由于UDP没有连接的概念,每次发送数据时,都可能从不同的端口发送;第一个发送不保留给定的端口,它只是从中发送一个数据报,然后放行。
您的服务器应该将自身绑定到特定端口。
UDP doesn't have connections. Datagrams are sent to and from ports; it's one-way communication.
It sounds to me like your server is letting itself be assigned a temporary port (i.e. passing 0 as the port in
sockaddr_in
), instead of using a specific port. This won't work.Since UDP has no concept of a connection, each time you send data, it could be sent from a different port; the first send doesn't reserve the port that it was given, it just sends a datagram from it and then lets it go.
Your server should be binding itself to a specific port.
嗯,这是防火墙问题。将应用程序添加到允许接收传入流量的程序列表中解决了该问题。
Meh, it was a firewall issue. Adding the application to the list of programs allowed to receive incoming traffic fixed the issue.