Reading UDP packets with several clients - c

I have an application installed locally (not developed by me), which broadcasts UDP packets every second.
Reading the packets from my application (developed in C++ in Windows) which also is locally installed, works fine.
WSADATA data;
WORD version = MAKEWORD(2, 2);
int wsOK = WSAStartup(version, &data);
SOCKET serverIn = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
sockaddr_in serverHint;
serverHint.sin_addr.S_un.S_addr = INADDR_ANY;
serverHint.sin_family = AF_INET;
serverHint.sin_port = htons(UDP_RECEIVE_PORT);
bind(serverIn, (sockaddr*)&serverHint, sizeof(serverHint));
sockaddr_in client;
int clientSize = sizeof(client);
int RECIEVE_BUFFER_SIZE = 65507;
char* recieveBuffer = new char[RECIEVE_BUFFER_SIZE];
while(updating)
{
int bytesIn = recvfrom(serverIn, recieveBuffer, RECIEVE_BUFFER_SIZE, 0, (sockaddr*)&client, &clientSize);
}
closesocket(serverIn);
WSACleanup();
But I recently noticed while I was testing some code, while my app was running, that the bind(...)
function returned an error code of 10048 (WSAEADDRINUSE). Hence, it seems the first client bound to listen for the UDP packets is the only one who can listen, and the other clients is unable to read the broadcasted UDP packets.
So then I added the SO_REUSEADDR option before calling the bind(...) function to be able to bind successfully to the socket:
BOOL bOptVal = TRUE;
int bOptLen = sizeof(BOOL);
setsockopt((SOCKET)serverIn, SOL_SOCKET, SO_REUSEADDR, (char*)&bOptVal, bOptLen);
That works, but the recvfrom(...) function then does not recieve any data at all! I guess it waits for the other client to close its socket.
Next solution is to initialize the socket with SOCK_RAW instead.
The above option SO_REUSEADDR is now not needed, and remove it:
SOCKET serverIn = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
This works, I can read the data now! Though, Windows now requires the adminstrator rights for my application. Also I do recieve the UDP information in the data which I do not need.
Is there any better method to do this without requiring administrator rights, any possibility to discard the header information in the buffer?

Below is a little program I wrote to demonstrate that IPv4 UDP broadcast can and does work as expected under Windows (i.e. without requiring raw-sockets or Administrator privileges).
Run it with the command line argument "server" and it will send out one broadcast UDP packet per second.
Then also run several more instances of the same program, with no command line arguments, to receive the UDP packets and print a line of text to stdout whenever they do. The expected behavior should look like this:
As for why it's not working for you -- one possible guess is that your UDP-packet-sending program is actually sending out unicast UDP packets rather than broadcast. If that's the case, then I would expect that only one client program would receive packets (even if multiple clients are bound to the same port). A network trace tool like Wireshark might be able to help you determine if the UDP packets being sent are broadcast or unicast.
Anyway, here's the code:
#include <stdio.h>
#include <ws2tcpip.h>
#pragma comment(lib,"WS2_32")
static int BindUDPSocket(SOCKET sock, unsigned short port, bool allowPortSharing)
{
if (sock == INVALID_SOCKET) return -1;
if (allowPortSharing)
{
const BOOL trueValue = true;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *) &trueValue, sizeof(trueValue)) < 0) return -1;
}
struct sockaddr_in bindAddr; memset(&bindAddr, 0, sizeof(bindAddr));
bindAddr.sin_family = AF_INET;
bindAddr.sin_addr.s_addr = INADDR_ANY; // aka 0.0.0.0
bindAddr.sin_port = htons(port);
return bind(sock, (struct sockaddr *) &bindAddr, sizeof(bindAddr));
}
int main(int argc, char ** argv)
{
WSADATA data;
WORD version = MAKEWORD(2, 2);
(void) WSAStartup(version, &data);
const unsigned short TEST_PORT = 12345;
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock<0) {printf("socket() failed\n"); exit(10);}
if ((argc > 1)&&(strcmp(argv[1], "server") == 0))
{
if (BindUDPSocket(sock, 0, false)<0) {printf("BindUDPSocket() failed for server\n"); exit(10);}
const BOOL allowBroadcast = true;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char *) &allowBroadcast, sizeof(allowBroadcast)) < 0)
{
printf("setsockopt(SO_BROADCAST) failed\n");
exit(10);
}
const char buf[] = {0x01, 0x02, 0x03, 0x04}; // dummy data
struct sockaddr_in toAddr; memset(&toAddr, 0, sizeof(toAddr));
toAddr.sin_family = AF_INET;
toAddr.sin_addr.s_addr = INADDR_BROADCAST; // aka 255.255.255.255
toAddr.sin_port = htons(TEST_PORT);
printf("Sending outgoing broadcast UDP sockets on port %u, once per second\n", TEST_PORT);
while(true)
{
if (sendto(sock, buf, sizeof(buf), 0, (const sockaddr *) &toAddr, sizeof(toAddr)) == sizeof(buf))
{
printf("Sent %zu bytes of broadcast UDP data\n", sizeof(buf));
}
else printf("sendto() failed!\n");
Sleep(1000); // wait 1 second
}
}
else
{
if (BindUDPSocket(sock, TEST_PORT, true)<0) {printf("BindUDPSocket() failed for client\n"); exit(10);}
printf("Waiting to receive incoming broadcast UDP sockets on port %u\n", TEST_PORT);
while(true)
{
char buf[1024];
const int ret = recv(sock, buf, sizeof(buf), 0L);
printf("Received %i bytes of incoming UDP data\n", ret);
}
}
}

Related

Why my socket doesn't receive any message?

In my code, I have this snippet:
char temp_buff[2048] = "";
strcpy(temp_buff, json_object_to_json_string(hb));
printf("%s\n", temp_buff);
char *str;
int fd = 0;
struct sockaddr_in demoserverAddr, cliaddr;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd < 0)
{
debug_level > 0 && printf("[SKT]\tError creating socket\n");
}
else
{
demoserverAddr.sin_family = AF_INET;
demoserverAddr.sin_port = htons(9100);
demoserverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(demoserverAddr.sin_zero, '\0', sizeof(demoserverAddr.sin_zero));
}
memset(&cliaddr, 0, sizeof(cliaddr));
int len=sizeof(cliaddr);
sendto(fd, temp_buff, strlen(temp_buff),MSG_CONFIRM, (const struct sockaddr *)&cliaddr, len);
On the other side, I write netcat -u -l 9100 in a terminal to see the incoming message, but nothing happens. Why?
You have two issues here.
First, by using SOCK_STREAM in the call to socket you're creating a TCP socket, but you're using sendto to and your netcat call is using the -u option indicating that you want to use UDP. So use SOCK_DGRAM instead.
Second, you're specifying cliaddr as the address to send to, but that variable was zero'ed out by memset. The demoserverAddr variable contains the IP and port of the remote server, so pass that to sendto. Also, be sure to check the return value.
int len=sizeof(demoserverAddr);
int rval = sendto(fd, temp_buff, strlen(temp_buff),MSG_CONFIRM,
(const struct sockaddr *)&demoserverAddr, len);
if (rval < 0) perror("sendto failed");

After I do a UDP broadcast, how do I know what port I broadcasted on?

I have a Linux C application that must use UDP. The server broadcasts a "discovery packet" and then listens for any connected clients to answer with a similar echo. By using ports, the clients and server can then communicate using their different ports.
Here is how the server broadcasts its discovery packet:
int main() {
puts("starting");
int sock;
int yes = 1;
struct sockaddr_in broadcast_addr;
int addr_len;
int count;
int ret;
fd_set readfd;
char buffer[1024];
char outbound_buffer[63];
int i;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("sock error");
return -1;
}
ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char*)&yes, sizeof(yes));
if (ret == -1) {
perror("setsockopt error");
return 0;
}
memset(outbound_buffer,0,sizeof(outbound_buffer));
addr_len = sizeof(struct sockaddr_in);
memset((void*)&broadcast_addr, 0, addr_len);
broadcast_addr.sin_family = AF_INET;
broadcast_addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
broadcast_addr.sin_port = htons(PORT);
outbound_buffer[0] = 0xEF;
outbound_buffer[1] = 0xFE;
outbound_buffer[2] = 0x02;
ret = sendto(sock, outbound_buffer, 63, 0, (struct sockaddr*) &broadcast_addr, addr_len);
This works fine; the client receives the discovery and gets the server's IP and port:
int main() {
stoplink = 0;
stopData = 0;
int addr_len;
int count;
int ret;
fd_set readfd;
char buffer[1024];
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("sock error\n");
return -1;
}
addr_len = sizeof(struct sockaddr_in);
memset((void*)&server_addr, 0, addr_len);
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htons(INADDR_ANY);
server_addr.sin_port = htons(PORT);
ret = bind(sock, (struct sockaddr*)&server_addr, addr_len);
if (ret < 0) {
perror("bind error\n");
return -1;
}
while (1) {
puts("Initialized; await discovery");
FD_ZERO(&readfd);
FD_SET(sock, &readfd);
ret = select(sock+1, &readfd, NULL, NULL, 0);
if (ret > 0) {
if (FD_ISSET(sock, &readfd)) {
count = recvfrom(sock, buffer, 1024, 0, (struct sockaddr*)&client_addr, &addr_len);
if((buffer[0] & 0xFF) == 0xEF && (buffer[1] & 0xFF) == 0xFE) {
fprintf(stderr,"discovery packet detected\n");
cmdport = ntohs(client_addr.sin_port);
printf("\nClient connection information:\n\t IP: %s, Port: %d\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
count = sendto(sock, buffer, strlen(buffer), 0, (struct sockaddr*)&client_addr,
sizeof(client_addr));
}
}
}
puts("Now starting command processing loop");
This also works fine... but it sends the reply to the port on the server from which the broadcast came - this was randomly selected automatically by the server; so how do I know what port to listen to on the server side to receive the client's reply?
The server doesn't need to do anything additional. Once it sends a packet, the port on the server side is set.
For example, if the client sees that the server message came from port 34567, then the server socket is using port 34567. Then any messages sent to the server at port 34567 can be read by the same server socket.
So the server can just call recvfrom and it will get the response from the client.
You've swapped the normal meanings of the words "client" and "server" -- normally the server will bind to a specific port and listen for (broadcast) packets, while the client will broadcast a discovery packet to find the server. When the server receives a broadcast, it will reply to the client, which will just do a recv on it's (single) socket to get the reply, which will have the server's IP address. If there might be multiple servers, then they'll all reply to the client, so the client will see multiple replies and need to choose from them. But, most importantly, the client never needs to actually know which port it is using -- it just lets the system choose an otherwise unused port for it.
Thanks for all the input. getsockname() is what I needed.

TCP cannot detect closed socket in client

I have server that just connects to a client and right after that disconnects, while client tries to send an integer to a closed socket (scanf is to ensure server closese it first). I use send with MSG_NOSIGNAL and check for EPIPE but the flag is not set. I think result should have printed value of -1, or 0, but it is equal to 1, because I am writing on already closed socket. Can someone explain that?
Server Code:
#define QUEUE_LENGTH 5
#define PORT_NUM 10002
#define BUFFER_SIZE 512000
int main(int argc, char *argv[]) {
int sock, msg_sock;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
socklen_t client_address_len;
sock = socket(PF_INET, SOCK_STREAM, 0); // creating IPv4 TCP socket
if (sock < 0)
syserr("socket");
server_address.sin_family = AF_INET; // IPv4
server_address.sin_addr.s_addr = htonl(
INADDR_ANY); // listening on all interfaces
server_address.sin_port = htons(PORT_NUM);
// bind the socket to a concrete address
if (bind(sock, (struct sockaddr *) &server_address,
sizeof(server_address)) < 0)
syserr("bind");
// switch to listening (passive open)
if (listen(sock, QUEUE_LENGTH) < 0)
syserr("listen");
printf("accepting client connections on port %hu\n",
ntohs(server_address.sin_port));
for (;;) {
client_address_len = sizeof(client_address);
msg_sock = accept(sock, (struct sockaddr *) &client_address,
&client_address_len);
if (msg_sock < 0)
syserr("accept");
printf("ending connection\n");
if (close(msg_sock) < 0) {
printf("ErrorClosingSocket\n");
break;
}
continue;
}
return 0;
}
Client code:
int sendSomething(void *to_send, int socket, uint32_t length) {
if (send(socket, to_send, length, MSG_NOSIGNAL) !=
length) {
if (errno == EPIPE) // Sending on closed connection
return 0;
return -1;
}
return 1;
}
int main(int argc, char *argv[]) {
int sock;
struct addrinfo addr_hints;
struct addrinfo *addr_result;
int err;
if (argc != 3)
fatal("Usage: %s host port\n", argv[0]);
// 'converting' host/port in string to struct addrinfo
memset(&addr_hints, 0, sizeof(struct addrinfo));
addr_hints.ai_family = AF_INET; // IPv4
addr_hints.ai_socktype = SOCK_STREAM;
addr_hints.ai_protocol = IPPROTO_TCP;
// argv[1] is localhost and argv[2] is 10002
err = getaddrinfo(argv[1], argv[2], &addr_hints, &addr_result);
if (err == EAI_SYSTEM) // system error
syserr("getaddrinfo: %s", gai_strerror(err));
else if (err != 0) // other error (host not found, etc.)
fatal("getaddrinfo: %s", gai_strerror(err));
// initialize socket according to getaddrinfo results
sock = socket(addr_result->ai_family, addr_result->ai_socktype,
addr_result->ai_protocol);
if (sock < 0)
syserr("socket");
// connect socket to the server
if (connect(sock, addr_result->ai_addr, addr_result->ai_addrlen) < 0)
syserr("connect");
freeaddrinfo(addr_result);
int result;
scanf("%d", &result);
uint16_t test;
test = htons(1);
result = sendSomething(&test, sock, sizeof(test));
printf("result:%d\n", result);
if (close(sock) < 0) {
printf("ErrorClosingSocket\n");
}
return 0;
}
Note: Fatal and Syserr are just for reporting errors
That's the way TCP works. When the server closes the socket, then a FIN is sent to the client. This only signals, that the server will not send any more data. It does not necessarily mean, that it does not want to receive more data.
Thus, the client can call send() on the socket without the OS reporting an error. If the server indeed closed the whole socket, then it will send a TCP reset packet as a response to incoming data indicating that condition. Now, future operations on the socket (write/close) will indicate an error.
It is indeed possible for the server (or any peer) to only shutdown the connection half-way (the reading or the writing side) with the syscall shutdown(). If the server shuts down the connection for writing, the same thing happens on the network as if the server closed the whole connection with close(). It is the duty of a higher level protocol to determine, when a connection should be closed for each side.
If you want to make sure, that all data that you sent was indeed acknowledged by the peer, you can use the SO_LINGER socket option. But a more common way is, to make this sure as a part of the communication protocol, i.e. one part requests to shutdown the connection on a higher level (for example, the smtp QUIT command) and the peer reacts on it by closing the tcp connection.

C sockets send UDP and process ICMP reply from router

I'm trying to send a UDP packet to a router with a time to live of 1, to then receive an ICMP time exceeded reply. So far I'm able to send the packet, but when my program gets to the recv part of the execution, it just hangs. I have an error check for recvfrom, but it doesn't even get to that. My computer is receiving the request. I know this because I run Wireshark when I run the program and I filter for ICMP requests. Every time I run the program, I receive the reply. What am I doing wrong with recvfrom?
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#define UNSPEC_PROTO 0
int main(int argc, const char *argv[])
{
if (argc != 2) {
printf("usage: routetracer <ip address or hostname>\n");
return -1;
}
struct addrinfo hints; //params for ret val of getaddrinfo
struct addrinfo* ret; //return value of getaddrinfo
struct sockaddr* reply_addr;
char ipv4[INET_ADDRSTRLEN];
char* msg = "THE PORT IS OVER 9000!!!!";
int status = 0;
int ttl = 0;
int src_sock = 0;
int recv_sock = 0;
socklen_t reply_addr_len = sizeof(struct sockaddr);
const char* dest_port = "9001";
int icmp_msg_len = 100;
char icmp_msg[icmp_msg_len];
//define what we want from getaddrinfo
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET; //IPv4
hints.ai_socktype = SOCK_DGRAM; //UDP packets
//call getaddrinfo to fill ret, w/ error chk
if ((status = getaddrinfo(argv[1], dest_port, &hints, &ret)) != 0) {
printf("getaddrinfo: %s\n", gai_strerror(status));
return -1;
}
//extract IPv4 address from ret
struct sockaddr_in* ip = (struct sockaddr_in *)ret->ai_addr;
//convert address from pure numbers to something easier to read
inet_ntop(ret->ai_family, &(ip->sin_addr), ipv4, INET_ADDRSTRLEN);
//kindly inform the user of which hostname they are connecting to
printf("Route for: %s\n", ipv4);
//create a socket for our machine
if ((src_sock = socket(ret->ai_family, ret->ai_socktype,
ret->ai_protocol)) < 0) {
fprintf(stderr, "Error creating host socket: %s\n", strerror(errno));
return -1;
}
//create a socket to recv icmp packet from hops
if ((recv_sock = socket(AF_INET, SOCK_DGRAM, UNSPEC_PROTO)) < 0){
fprintf(stderr, "Error creating recv socket: %s\n", strerror(errno));
}
/*
* We go from hop to hop by incrementing the time to live in the IP header
* for each hop we visit until we reach the destination IP address (which we
* already have). Time to live decrements for every hop, so once it reaches
* zero we report the IP address of the node we are connected to.
*/
//while(test_ip != dest_ip)
//time_to_live++
//send_to(dest_addr)
//receive icmp error message
//get src addr of error msg from ip header of icmp
//test_ip = src addr
/*
while (last_hop == 0) {
ttl++;
setsockopt(sock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
sendto(sock, msg, strlen(msg), 0, (struct sockaddr *)ip, sizeof(ip));
}
*/
ttl = 1;
if (!(setsockopt(src_sock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)))) {
printf("TTL set successfully\n");
} else {
printf("Error setting TTL: %s\n", strerror(errno));
}
if ((sendto(src_sock, msg, strlen(msg), 0, ret->ai_addr,
ret->ai_addrlen)) > 0) {
printf("msg sent successfully\n");
} else {
fprintf(stderr, "Error sending msg: %s\n", strerror(errno));
}
if ((recvfrom(recv_sock, icmp_msg, icmp_msg_len, 0, reply_addr,
&reply_addr_len)) != -1) {
/* PROCESS THE INFORMATION */
printf("Packet received\n");
} else {
fprintf(stderr, "Error receiving packet: %s\n", strerror(errno));
}
return 0;
}
Normally, UDP pretty much ignores ICMP errors, so if you want to see them, you need to open a raw socket to receive all ICMP packets and look for ones relevant to your socket.
On Linux, at least, an alternative is to set the IP_RECVERR socket option. If you do that, you can do a recvmsg with the MSG_ERRQUEUE flag set to get any ICMP (or other) errors associated with your socket. This has the advantage of not requiring elevated privileges or a second socket.
In some implementations of sockets, UDP socket has to be connected to receive errors.
So, you need to add connect call and then use send/recv functions.
I've confirmed this on FreeBSD. At least one source clearly states that:
http://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-5.html (see 5.3 Does doing a connect() call affect the receive behaviourof the socket?)
P.S. Note, however, that you won't receive exact ICMP error message that way. You'll only get some error code, without many details (if any).
Check the options when you are opening your sockets.
See How to sniff all ICMP packets using RAW sockets.
See How to receive ICMP request in C with raw sockets.
You may also want to change the socket options to be non-blocking and use the select() function to determine if there is something to read or not.
For examples on using the select() function see the following.
Blocking recvfrom with select system call.
Unexepcted results with select and recvfrom.
First of all, your code has undefined behavior, because reply_addr is uninitialised. You should fix that first:
struct sockaddr_in reply_addr;
...then:
recvfrom(recv_sock, icmp_msg, icmp_msg_len, 0, (struct sockaddr*)&reply_addr,
&reply_addr_len);
Finally, you need to use raw sockets, not datagram sockets, to receive ICMP packets:
recv_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

client socket unable to receive data using poll/select

/* SEND FUNC. */
int mysend(unsigned char *buffer, int len) {
int sock,ret;
int status,flags;
struct sockaddr_in6 servaddr;
int opt = 1;
char *addr = "1101::1";
sock = socket(AF_INET6,SOCK_DGRAM,0);
if (sock < 0)
return -1;
if( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
return -1;
flags = fcntl(sock, F_GETFL, 0);
fcntl(sock, F_SETFL, flags|O_NONBLOCK);
servaddr.sin6_family = AF_INET6;
servaddr.sin6_port = htons(61616);
status = inet_pton(AF_INET6, addr, &servaddr.sin6_addr);
if (status <= 0) {
perror("inet_pton");
return -1;
}
/* send message to server */
status = sendto(sock, buffer, len, 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
if (status < 0) {
perror("sendto");
return -1;
}
close(sock);
printf("MESSAGE SENT SUCCESSFULLY\n");
return 0;
}
/* RECEIVE FUNC. */
int myrcv() {
int sock,ret;
int status,len,rx_bytes;
int timeout,nfds =1;
struct sockaddr_in6 servaddr;
struct timeval wait;
unsigned char rxbuff[1024];
char *rcv;
char *addr = "1101::1";
fd_set rd;
struct pollfd *fds;
sock = socket(AF_INET6,SOCK_DGRAM,0);
if (sock < 0)
return -1;
servaddr.sin6_family = AF_INET6;
servaddr.sin6_port = htons(61616);
status = inet_pton(AF_INET6, addr, &servaddr.sin6_addr);
if (status <= 0)
return -1;
bind(sock,(struct sockaddr *)&servaddr,sizeof(servaddr));
timeout = (1* 1000);
wait.tv_sec = 10;
wait.tv_usec = 0;
len = sizeof(servaddr);
fds->fd = sock;
fds->events = POLLIN;
for(;;) {
//FD_ZERO(&rd);
//FD_SET(sock,&rd);
printf("Waiting for data....\n");
ret = poll(fds,nfds,timeout);
//ret = select(1,&rd,NULL,NULL,&wait);
if(ret < 0)
break;
if(fds->revents == 0)
printf("revents 0 %d\n",ret);
if(ret == 0)
continue;
memset(rxbuff,0,1024);
//if(FD_ISSET(sock,&rd)) {
printf("receiving message\n");
rx_bytes = recvfrom(sock,rxbuff,1024,0,(struct sockaddr *)&servaddr,&len);
memcpy(rcv,rxbuff,rx_bytes);
//}
}
close(sock);
return 0;
}
int main()
{
/* call mysend() periodically using sigaction() */
/* create a thread that continuously monitors(calls myrcv()) for incoming data */
return 0;
}
I'm unable to receive the packets from the server, but I could see the packets in the tcpdump output. Above are the sample client code snippets, which tries to receive and send the data from/to the server. The scenario is: the client needs to send data periodically to server and should also be able to receive any data from the server.
I have tried using both poll and select methods but failed to receive. Please let me know if I'm missing anything. Thanks for your support.
The problem you have with receiving is that you need to bind the receiving socket to the local port.
You also have other things that can be improved, like creating a single socket for both sending and receiving and using SO_REUSEADDR on the sending socket (not needed on a write-only socket).
What you should do is:
Create socket
Set socket options
Bind to local address (Use IN6ADDR_ANY_INIT to bind to all interfaces)
Write to server
Poll for reply
Several things:
Your receive function (myrcv) isn't specifying a listen port via the bind() call. That's the most likely problem. Ditto for your send function, although a port is chosen randomly for you.
In you myrcv() function, I don't see where you have actually initialized fds or nfsd prior to calling poll().
Re-opening and closing the socket on each call to mysend() looks problematic. If you are expecting the server to send back to the same client on the same port it received the message on, chances are high you have already closed the socket. You should just open one socket for both sending and receiving. You can share the same socket between your send thread and your receive thread.

Resources