Here is what I have so far (stripped error checking):
struct sockaddr_in addr, ss, dest;
int port, s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
fcntl(s, F_SETFL, fcntl(s, F_GETFL, 0) | O_NONBLOCK);
memset((char*) &addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
inet_aton("127.0.0.1", &addr.sin_addr);
bind(s, (struct sockaddr*) &addr, sizeof(addr));
unsigned int len = sizeof(ss);
getsockname(s, (struct sockaddr*) &ss, &len);
port = ss.sin_port;
memset((char*) &dest, 0, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(port);
inet_aton("127.0.0.1", &dest.sin_addr);
sendto(s, "test", 5, 0, (struct sockaddr*) &dest, sizeof(dest));
char buf[5];
recv(s, buf, 5, 0);
The last sentence fails with a message of Resource temporarily unavailable (because of the O_NONBLOCK flag).
In the snippet I let the OS to bind a random port, and then I obtain it with getsockname. If I use a fixed port instead and remove the call to getsockname then it works.
PS: I’m on a linux machine.
You forgot to use
ntohswhen you captured the OS-assigned port. Here’s what I ended up with (I did a couple small things to make the code more concise too):