UDP client does not receive data without bind() - c

I refereed to the UDP client program from binarytides and I was able to send a UDP packet frompy PC to the UDP server which is My embedded device and this device echoes back a UDP message.
In this PC-UDP client code it is expected to get the echoed message ,but I'm not getting any echoes back.So I ran a UDP server in my PC which listens for the incoming data and prints it , I was able to see the echoed message from my Embedded device.
When I added these lines just before the while(1) loop in the code,and now I'm able to see the Echoed back message.
//setup address structure
memset((char *) &si_server, 0, sizeof(si_server));
si_server.sin_family = AF_INET;
si_server.sin_port = htons(PORT);
si_server.sin_addr.S_un.S_addr = INADDR_ANY;
if( bind(s ,(struct sockaddr *)&si_server , sizeof(si_server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
Any thoughts on what might be causing the issue?

Hi Finally I found the answer from EJP answer
It is only necessary to bind() a server, because the clients need a fixed port number to send to. A client needn't bind() at all: an automatic bind() will take place on the first send()/sendto()/recv()/recvfrom() using a system-assigned local port number.
With the help of wireshark I was able to see My PC was sending data from Port 53701 and on first sendto() this port got automatically bind'ed , so had to do a explicit binding.

Related

How to solve "Address already in use" when restarting a client-server application?

I have a client-server application written in C. A hardcoded port number is used for socket communication between the client and the server. After every run of the application, I have to wait for some time before restarting it again given that the socket enters the TIME_WAIT state after the server exists. If I don't wait, the new run of the server errors out with "Address already in use". My code is based on Beej's Guide to Network Programming. Here is the sequence of calls made on the server side:
sock = socket(...);
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &OK, sizeof(int)); //OK=1
bind(sock, ...);
listen(sock, BACKLOG);
while(someCondition) {
select(sock+1, &readFDs, NULL, NULL, &timeout);
newSock = accept(sock, ...);
recv(newSock,...);
send(newSock,...); // ACK
close(newSock);
}
close(sock);
return 0;
On the client side, a connection is established to send a request to the server and then closed as soon as a response is received from the server. The sequence of calls is as follows:
clientSock = socket(...);
connect(clientSock, ...);
send(clientSock, ...);
recv(clientSock, ...);
close(clientSock);
Is there a way to be able to restart the server immediately without having to wait?
Can I avoid that the socket created by the server enters the TIME_WAIT state?
Is there a way to pick a different port for every run?

connect is unsuccessful in my socket programming function in C

I have a function which initiates the socket connection. I am trying to a server with a name let's say xp. Socket() is working fine. But when it comes to connect, I am getting an error. I tried to get the IP of that server, I got some random IP. I passed the parameters to the connect API. I print the results of these in a log file. I think error lies within the connect(). I am working on Linux Ubuntu. Here is my program for SocketInit(). I can't get the error with that.
I call the SocketInit function as
SocketInit(argv[2]); argv[2] has my server name.
short SocketInit(char *xp)
{
if ( (local_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
printf("socket creation is unsuccessful check in SocketInit() \n");
sprintf(log_msg, "create socket descriptor error = %d", errno);
LogMsg('E', log_msg);
return(-1);
}
else
{
printf("socket connection is success\n");
}
pos_socket.sin_family = AF_INET;
pos_socket.sin_port = htons(port_no);
pos_socket.sin_addr.s_addr = inet_addr(xp);
if ( connect( local_socket, (struct sockaddr *) &pos_socket, sizeof(pos_socket) ) < 0 ) {
sprintf(log_msg, "connect on socket error=%d", errno);
printf("socket connect api is unsuccessful check in SocketInit() \n");
LogMsg('E', log_msg);
return(-1);
}
else{
printf("connect is successful\n");
return 0;
}
}
How can I connect to the server. How can I pass the address to the pos_socket.sin_addr.s_addr ? Sometimes I get connect error 110 and 111. But still I can't connect.
Use perror() to print the human-readable error string when connect() or most other unix-like system calls return an error. But since you told us the value of errno, I looked in errno.h for the meaning, and found:
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
(BTW, you cannot count on errno's being the same from one unix to another which is why you need to use these defines when checking for specific errors. Never hard-code numeric errno values into your code. It worked out for me this time, but it won't necessarily every time).
ECONNREFUSED means that there was a machine listening at the specified IP address, but that no process was listening for connections on the specified port number. Either the remote process is not running, it is not binding or accepting connection properly, or it potentially could be blocked by some sort of firewall.
In any case, this points to a problem with the server.
So, check to make sure your remote process is actually ready to accept the connection. You can use telnet or netcat as a test client to see if other client programs that are known to work are able to connect to your server.
Also, I notice that your variable port_no is not declared, so we have no way of knowing what port you are trying to connect to.. but make sure that this variable is of the correct type and has the correct value for the service you are trying to connect to. If port_no doesn't specify the correct port you will get the same type of error.

2 user space programs over tun using multicast

I am still getting my hands-on with networking programming for linux and please feel free to clear my understanding if you feel its vague or incorrect.
Query:
I have baked a Linux image using yocto project which is similar to core-image-minimal. This part is irrelevant for the query. I boot this image using QEMU emulator and when QEMU is booted up it creates a sudo interface by the name tap0. The IP of the QEMU is 192.168.7.2 and tap0 i guess has IP 192.168.7.1.
Now I have another user space program written in simple C which tries to listen whatever the QEMU program(node) is sending. So, I use a fragment similar to this:
if ( (fd = open("/dev/net/tun",O_RDWR)) < 0) PERROR("open");
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = TUNMODE;
strncpy(ifr.ifr_name, "w-tap%d", IFNAMSIZ);
if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) PERROR("ioctl");
printf("Allocated interface %s. Configure and use it\n", ifr.ifr_name);
s = socket(PF_INET, SOCK_DGRAM, 0);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(PORT);
if ( bind(s,(struct sockaddr *)&sin, sizeof(sin)) < 0) PERROR("bind");
fromlen = sizeof(from);
while(1) {
l = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
//print the data etc
}
Now If I start this C code with say sudo ./tun_proxy 1534, I am able to listen the messages on this port sent by 192.168.7.2.
Further,
I Boot up QEMU with additional option -net socket,mcast=224.244.224.245:30490 since baked image has a small program in it to send some messages as broadcast on the multicast group and port. Also, I should be able to listen these message on the previous tun_proxy application. I even created a new thread in that which tries to listen on the multicast group but I get the error message as "already in use"
Where exactly is my understanding wrong? All I need is 2 user space programs, one of which is a QEMU to communication via multicast messages.
Your understanding is sound, there are just 2 problems you need to address:
If you bind on INADDR_ANY you are blocking the port for all other addresses (including multicast) unless you use REUSEADDR. Your INADDR_ANY bound socket would also be receiving the multicast it is blocking access to, except:
Some socket on a "host" needs to use IP_ADD_MEMBERSHIP where the membership request matches the traffic before any sockets will receive the multicast traffic.
Emulating your current example:
As an equivalent but rather bizarre example, shell1 is equivalent to your listener and shell2 shows that a seemingly unrelated socket's ip-add-membership (but for the correct address and all interfaces) causes it to receive traffic:
shell1$ socat UDP-RECVFROM:30490,bind=0.0.0.0 EXEC:date
shell2$ echo hi | socat UDP-DATAGRAM:224.244.224.245:30490 STDIO
shell1$ (socat is still waiting for a packet)
shell2-add-membership$ socat UDP-RECVFROM:1044,reuseaddr,bind=127.0.0.1,ip-add-membership=224.244.224.245:0.0.0.0 EXEC:date&
[1] 16003
shell2$ echo hi | socat UDP-DATAGRAM:224.244.224.245:30490 STDIO
Thu Sep 1 00:16:28 CEST 2016
shell1$ (socat now exits cleanly)
Fixing it for multicast:
So to run 2+ clients, the correct method would be:
shellclient1$ socat UDP-RECVFROM:30490,bind=0.0.0.0,reuseaddr,ip-add-membership=224.244.224.245:0.0.0.0 EXEC:date
shellclient2$ socat UDP-RECVFROM:30490,bind=0.0.0.0,reuseaddr EXEC:date
...
shellclientn$ socat UDP-RECVFROM:30490,bind=0.0.0.0,reuseaddr EXEC:date
shell2$ echo hi | socat UDP-DATAGRAM:224.244.224.245:30490 STDIO
Thu Sep 1 00:16:28 CEST 2016
...
Notice that all must use SO_REUSEADDR, but only one must add membership.
Qemu's socket network uses SO_REUSEADDR and does an membership. So the code blocking the socket is probably other code that needs to be modified to be like Qemu.

why i am getting Remote ip address 0.0.0.0 from recvfrom()?

I have a server listening on a port
The request is sent from my local client to the server running on my local pc.
Following is my code snippet
remote_len = sizeof(remote_addr);
if ((bytes=recvfrom(sockfd, buf, MAXBUFLEN , 0,
(struct sockaddr *)&remote_addr, &remote_len)) <= 0) {
exit(1);
}
printf("remote ip = %s\n",inet_ntoa(remote_addr.sin_addr));
When i print the ip i get 0.0.0.0 ??
Is this not the remote IP adrress which i am trying to print?
Edit : Its a TCP socket and i recevied buffer successfully.
See TCP recvfrom() doesn't store 'from' - apparently it's not supported for TCP. All you're seeing is the zero bytes that were originally there. That's why remote_len returns 0 - because no address was set.
That link is to windows related docs; I don't see that behaviour in the Linux man page, which says only "may be used to receive data on a socket whether or not it is connection-oriented", but at http://www.beej.us/guide/bgnet/output/html/multipage/recvman.html it says that recvfrom is for UDP. It's not mentioned in Harbison + Steele, unfortunately, and I can't find a copy of Unix Network Programming.

what's the host port number when we use accept() and connect() in C socket programming

the Beej's Guide to Network Programming explains the accept() as follows:
What's going to happen is this: someone far far away will try to connect() to your machine on a port that you are listen()ing on. Their connection will be queued up waiting to be accept()ed. You call accept() and you tell it to get the pending connection. It'll return to you a brand new socket file descriptor to use for this single connection!
but how do we know the port number of the "brand new socket"?
Pass the accepted SOCKET to getsockname() to retreive its local IP/Port, and to getpeername() to retreive its remote IP/Port.
I think getpeername will return this information
From the GNU docs on accept.
newfd = accept (sockfd, (struct sockaddr *) &clientname, &size);
if (newfd < 0) {
perror ("accept");
exit (EXIT_FAILURE);
}
In the accept sockaddr.in struc, you find the local port.
fprintf (stderr, "Server: connect from host %s, port %hd.\n",
inet_ntoa (clientname.sin_addr),
ntohs (clientname.sin_port));
It does not assign a new port. The accepted socket uses the same port as the listening socket.

Resources