1
votes

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?

2

2 Answers

2
votes

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.

0
votes

Meh, it was a firewall issue. Adding the application to the list of programs allowed to receive incoming traffic fixed the issue.