Basic UDP Client/Server won't work? - c

I am hoping that this is a relatively simple answer to my question. I am attempting to learn how to program in sockets and I just can't seem to get a basic UDP example working. I am attempting to just send a string "hello" from one computer to another read it on the screen.
I started with this website
https://www.programminglogic.com/sockets-programming-in-c-using-udp-datagrams/
then tried:
https://www.abc.se/~m6695/udp.html
I have also looked at
https://www.cs.rutgers.edu/~pxk/417/notes/sockets/udp.html
but it seems that each time I try to code nothing happens. I get no errors, I just don't get any communication. I can ping my server computer from my client computer at least
My setup:
I currently have two computers one running Ubuntu 16.04 the other 14.04.
I was hoping to start off with something easy by connecting them directly. But I have tried connecting them through a switch. No success.
On the "server" computer I set up my network card to have by opening the terminal and
sudo ifconfig enps60 192.168.1.1 netmask 255.255.255.0
To create my server code in terminal I type
gedit udp_server.c
and in the text editor I type
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <ctype.h>
int main()
{
int udpSocket, nBytes;
char buffer[1024];
struct sockaddr_in serverAddr, cientAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size, client_addr_size;
/* Create UDP socket */
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
/* Configure settings in address struct */
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(0);
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.1");
memset(serverAddr.sin_zero, '\0', sizeof(serverAddr.sin_zero));
/* Bind Socket */
bind(udpSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
printf("bind complete. Port number = %d\n", ntohs(serverAddr.sin_port));
addr_size = sizeof(serverStorage);
while(1)
{
nBytes = recvfrom(udpSocket, buffer, 1024, 0, (struct sockaddr *)%clientAddr, &addr_size);
printf("any bytes: %d\n, nBytes);
}
}
I then compile my code in terminal by typing
gcc -o udp_server udp_server.c
On my client computer (ubuntu 14.04) I open the terminal and type
sudo ifconfig eth0 192.168.1.2 netmask 255.255.255.0
then to create my client code in terminal I type
gedit udp_client.c
and in the text editor I type
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main()
{
int udpSocket, portNum, nBytes;
char buffer[1024] = "hello";
struct sockaddr_in serverAddr;
socklen_t addr_size;
unsigned int alen;
/*create UDP socket */
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
/* Configure settings in address struct */
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(0);
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.1");
memset(serverAddr.sin_zero, '\0', sizeof(serverAddr.sin_zero));
addr_size = sizeof(serverAddr);
while(1)
{
printf("sending %s\n", buffer);
nBytes = strlen(buffer);
sendto(udpSocket, buffer, nBytes, 0, (struct sockaddr *)&serverAddr, addr_size);
sleep(1);
}
return 0;
}
I apologize if my code isn't that polished also.

Ok, well thanks guys for all the suggestions, but I do have some code that works.
I still am very unsure how any of this works, but for starters I was selecting an incorrect port number. According to Steve Summitt I checked my connection using Netcat, and when I would look at port 0 netcat would kindly let me know that I can't choose a port number that low. This is a bit confusing as everything I am reading says that port numbers start at 0. Also there is a thing about trying not to use well known ports which used to be 0-255 but is now 0-1023. I was trying to figure out if I know what ports I can use or not and I came across this.
https://sort.veritas.com/public/documents/vie/7.3/aix/productguides/html/sfcfsha_config/apgs04s03.htm
Although I am unsure the context is only when using IPv6 protocol?
Also I found this list.
https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
I guess there are a bunch of applications on every machine that uses these ports?
The quick solution: I set the port to 1024 and forgot to bind my client socket to my client computers network card. I also changed the way I do memset (I thought I understood it, but I might not)
for the complete solution:
Current Setup:
I have two Ubuntu machines connected together by a simple switch. The machines are what I am calling a server (ubuntu 16.04) and a client (ubuntu 14.04).
The first step I did is assign static IPs to each machine (I think this is only recommended for my server computer, but I didn't know how to get my DHCP address of my client in c).
in my server computer I opened my terminal (ctrl + alt + t)
sudo ifconfig enp6s0 192.168.1.1 netmask 255.255.255.0
in the client computer I opened my terminal and typed
sudo ifconfig eth0 192.168.1.2 netmask 255.255.255.0
now going back to the server computer in terminal I typed
gedit udp_server.c
which opened up a text editor
/************** UDP Server Code *****************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <ctype.h>
int main()
{
int udpSocket, nBytes;
char buffer[5];
struct sockaddr_in serverAddr, clientAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size, client_addr_size;
int i;
/* Create UDP socket */
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
/* Configure settings in address struct */
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(1024);
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
memset(serverAddr.sin_zero, '\0', sizeof(serverAddr.sin_zero);
/* Bind socket with address struct */
bind(udpSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
printf("bind complete port number %d\n", ntohs(serverAddr.sin_port));
/* Initialize size variable to be used later on */
addr_size = sizeof(serverStorage);
while(1)
{
nBytes = recvfrom(udpSocket, buffer, 5, (struct sockaddr *)&clientAddr, &addr_size);
printf("any bytes %d\n", nBytes);
}
return 0;
}
now for the client code I typed (on my client computer)
gedit udp_client.c
which opened up a text editor
/************ UDP client code **********/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdlib.h>
int main()
{
int udpSocket, portNum, nBytes;
char buffer[1024] = "hello";
struct sockaddr_in serverAddr, clientAddr;
socklen_t addr_size;
unsigned int alen;
/* Create UDP socket */
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
/* Configure client settings in address struct */
memset((char *)&clientAddr, 0, sizeof(clientAddr));
clientAddr.sin_family = AF_INET;
clientAddr.sin_addr.s_addr = inet_addr("192.168.1.2");
clientAddr.sin_port = htons(0);
if(bind(udpSocket, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0)
{
perror("bind failed");
return 0;
}
printf("client bound");
/* configure server settings in struct */
memset((char *)&serverAddr, '0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(1024);
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.1");
printf("the socket ip addr is: %s\n", inet_ntoa(clientAddr.sin_addr));
addr_size = sizeof(serverAddr);
while(1)
{
sleep(2);
nBytes = strlen(buffer);
if(sendto(udpSocket, buffer, nBytes, 0, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1)
{
perror("send to");
exit(1);
}
printf("sent %s\n", buffer);
}
return 0;
}
some extra notes
I actually don't know if I need to bind my sockets on my client side? I bound it to port 0 and everything worked peachey. I am thinking might run into issues if I try to receive from the server?
I am still working on a metaphor for how to think about ports
I am going with that the IP address is the network card address (city) and the port number is the address within that city (task, application). Like many people can reside in a city, many tasks or programs can reside on a machine and each one might want to communicate to the world.
This is only the most basic information (I don't cover other things like connect(), send(), write(), sendmsg() as I don't know how to use them)
hopefully this post makes it easier on the next guy.

Related

How to setup a local server for simple data transmission (UDP/TCP)

I'm currently working with some gps tracking devices for a college project but I need to setup a local server to send data to (I can define to which IP address and PORT the data is sent to).
Since the data sent from the device is a string with multiple bytes written on binary code (it contains information about geographical localization, temperature and humidity values, etc.), I'm looking to actually see the whole string (my idea would be to store it on a notepad so I could manually see how the string looks like) as well as decode the whole string (slicing it into little information packages: "first part" corresponds to coordinates; "from here to there" corresponds to the value of temperature sensor 1; etc.).
Since all of this takes time and multiple codifications, I would like to first understand how to setup a local server (or if thats even possible) in order to simply see the string sent by my "client".
My knowledge in client/server communication is basic, I understand the base concept and I'm reasonable at coding sockets (which I probably need to use to establish my connection, server side).
Any help would be appreciated!
EDIT :
Client
// Client side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
// Driver code
int main() {
int sockfd;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = INADDR_ANY;
// Sending message to server
sendto(sockfd, "Hello", 5, 0, (const struct sockaddr *) &servaddr, sizeof(servaddr));
printf("Message sent.\n");
close(sockfd);
return 0;
}
Server
// Server side implementation of UDP client-server model
#define PORT 8080
#define MAXLINE 1024
// Driver code
int main() {
int sockfd, len;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
struct sockaddr_in servaddr, cliaddr;
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));
// Filling server information
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
// Bind the socket with the server address
if ( bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) {
perror("bind failed");
exit(EXIT_FAILURE);
}
char buffer[MAXLINE];
len = sizeof(cliaddr);
int n = recvfrom(sockfd, buffer, sizeof(buffer) -1, 0, ( struct sockaddr *) &cliaddr, &len);
if (n < 0)
perror("rcvfrom failed");
buffer[n] = '\0';
printf("%d bytes sent by client: %s\n", n, buffer);
return 0;
}
1 - Google for a simple TCP or UDP server-client application you will find plenty of them,
2 - Get your server running first, then use something like telnet to connect to it, send your first message to your server. (probably use a sample message that your client will send). Try sending messages from another device while it is in the same network and it is not in the same network,
3 - Reshape your server as to parse and evaluate the messages it will receive (NMEA sentences or whatever it receives)
4 - Then go all the way back to the example code and implement your client upon it. Building a client should take less time relatively.
I assumed you can handle listening GPS and other sensors. Good luck.

Only one of two UDP listeners receives message

I'm trying to extend the example from here, to having to services receiving the same message from the same UDP port.
From this question, I understand that I should use SO_REUSEADDR to avoid the error of "address already in use". I have one client sending a "hello" message om port 8080 and two identical services, which simply prints out the received message from the port. SO_REUSEADDR solved the problem of using the same address, however only one of the services receives and prints out the message, while the other keep waiting.
Would it not be possible to have the same message received by both services?
The client:
// Client side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define MAXLINE 1024
// Driver code
int main() {
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from client";
struct sockaddr_in servaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
// Filling server information
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = INADDR_ANY;
int n, len;
sendto(sockfd, (const char *)hello, strlen(hello),
MSG_CONFIRM, (const struct sockaddr *) &servaddr,
sizeof(servaddr));
printf("Hello message sent.\n");
close(sockfd);
return 0;
}
One of the two identical services:
// Server side implementation of UDP client-server model
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define MAXLINE 1024
// Driver code
int main() {
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from server";
struct sockaddr_in servaddr, cliaddr;
// Creating socket file descriptor
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
int reuse = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0)
perror("setsockopt(SO_REUSEADDR) failed");
#ifdef SO_REUSEPORT
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0)
perror("setsockopt(SO_REUSEPORT) failed");
#endif
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));
// Filling server information
servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);
// Bind the socket with the server address
if ( bind(sockfd, (const struct sockaddr *)&servaddr,
sizeof(servaddr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
int len, n;
len = sizeof(cliaddr); //len is value/resuslt
n = recvfrom(sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, ( struct sockaddr *) &cliaddr,
&len);
buffer[n] = '\0';
printf("Client : %s\n", buffer);
return 0;
}
I think that Sockets act like a queue to your application. Each message received from the network gets placed in that queue, and applications calling recv() or recvfrom() pop messages off of that queue.
The two clients using the same UDP port will share the same queue. I think calling recvfrom() on one client will pop a message off of the queue for that client, and make that message unavailable for the other client.
I think that generally the best approach is to have a one-to-one relationship between clients and sockets.
But, you're curious and really want the message to be available for both clients, you could experiment with passing the MSG_PEEK flag to recvfrom(). That flag changes recvfrom() to not consume the next message from the socket queue, so the other client could also receive it.

use sockets to read an RFID device from the network using C

I found an RFID reader with a finger print reader that I would like to use. I tried to use sockets to listen to the port, but I'm unsure on how can I do it properly. The device does not have any labels, so I cannot find data from manufacturer on how to establish the connection. The devices works as I have tested with another software used for clocking in, so the device has now an IP address assigned that I'm able to ping. I have tried a socket server program to listen to the port, but I'm not getting anything when I read the RFID tags. How can I read data from the device when it is connected to the network and store the data?
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
main(){
char server_message[256] = "You have reached the server";
//create the server socket
int server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, 0);
//define the server address
struct sockaddr_in server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(9002);
server_address.sin_addr.s_addr = INADDR_ANY;
//bind the socket to our specified IP and port
bind(server_socket, (struct sockaddr *) &server_address, sizeof(server_address));
listen(server_socket, 5);
int client_socket;
client_socket = accept(server_socket,NULL,NULL);
char server_response[256];
recv(server_socket, &server_response, sizeof(server_response), 0);
//print out server's response
printf("The server sent the data: %s\n", server_response);
//send the message
send(client_socket, server_message, sizeof(server_message), 0);
//close the socket
close(server_socket);
return 0;
}

Address family not supported by protocol

The following code is a socket programming sample for a TCP client.
But when I run this, connect() is returned as Address family not supported by protocol.
I have heard, this problem will happen if the platform does not support ipv6.
But AF_INET I wrote is ipv4.
Also my server, that is CentOS6.4, is configured within an inet6 addr .
Does anyone know why?
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int
main(){
struct sockaddr_in server;
int sock;
char buf[32];
int n;
sock = socket(AF_INET,SOCK_STREAM,0);
perror("socket");
server.sin_family = AF_INET;
server.sin_port = htons(12345);
inet_pton(AF_INET,"127.0.0.1",&server,sizeof(server));
connect(sock,(struct sockaddr *)&server,sizeof(server));
perror("connect");
memset(buf,0,sizeof(buf));
n = read(sock,buf,sizeof(buf));
perror("read");
printf("%d,%s\n",n,buf);
close(sock);
return 0;
}
The code passes the wrong destination address and wrong number of arguments to inet_pton(). (For the latter the compiler should have warned you about, btw)
This line
inet_pton(AF_INET, "127.0.0.1", &server, sizeof(server));
should be
inet_pton(AF_INET, "127.0.0.1", &server.sin_addr);
Verbatim from man inet_pton:
int inet_pton(int af, const char *src, void *dst);
AF_INET
[...] The address is converted to
a struct in_addr and copied to dst, which must be sizeof(struct in_addr) (4) bytes (32 bits) long.
Not related to the problem, but also an issue, is that read() returns ssize_t not int.
The following lines shall be adjusted:
int n;
[...]
printf("%d, %s\n", n, buf);
to become:
ssize_t n;
[...]
printf("%zd, %s\n", n, buf);
Set the server address like this;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(host);
addr.sin_port = htons(port);
I seen this error during bind. Cause was of using localhost instead of IP:
./myprogram localhost:7777
*** exception! `bind' failed for `localhost:7777' (97, Address family not supported by protocol)
./myprogram 127.0.0.1:7777
OK! Listening...
In addition: this error happens on one Linux host and does not appear on another. I check and compare network settings on this machines (lo device, /etc/hosts, /etc/host.conf, etc) and not found essential difference

Send / receive data over network in C

I have written this program:
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int socket_desc;
struct sockaddr_in adress;
int addrlen;
int new_socket;
int bufsize = 1024;
char *you_sent = "You sent: ";
int main() {
char *buffer = malloc(bufsize);
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
adress.sin_family = AF_INET;
adress.sin_addr.s_addr = INADDR_ANY;
adress.sin_port = htons(7000);
bind(socket_desc, (struct sockaddr *)&adress, sizeof(adress));
listen(socket_desc, 3);
addrlen = sizeof(struct sockaddr_in);
new_socket = accept(socket_desc, (struct sockaddr *)&adress, &addrlen);
while(recv(new_socket,buffer,bufsize,0))
{
printf("I recieved: %s", buffer);
send(new_socket, you_sent, strlen(you_sent), 0);
send(new_socket, buffer, strlen(buffer), 0);
memset(buffer, '\0', sizeof(buffer));
}
}
I can connect to the server with a telnet. And write stuff to the application and recieve data from the application.
But i cannot get my head around how i can connect to this with another c program and send and recieve data from that program.
I have tried this:
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int socket_desc;
struct sockaddr_in adress;
int addrlen;
int new_socket;
char *message_to_send = "Hello world!";
int main() {
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
adress.sin_family = AF_INET;
adress.sin_addr.s_addr = INADDR_ANY;
adress.sin_port = htons(7000);
bind(socket_desc, (struct sockaddr *)&adress, sizeof(adress));
listen(socket_desc, 3);
addrlen = sizeof(struct sockaddr_in);
new_socket = accept(socket_desc, (struct sockaddr *)&adress, &addrlen);
send(new_socket, message_to_send, strlen(message_to_send), 0);
}
A server is like a telephone operator on a switch board. That person does the following:
Sits in front of a phone (i.e. bind to a number)
Waits for it to ring (i.e. listen)
Picks up the phone (i.e. accept)
The person at the other end just wants to make a call to that person. (i.e. connect). The person only needs to go to the phone when a call needs to be made. Therefore not bound to the phone or has to listen for it to ring.
I hope this metaphor helps in your understanding.
PS: The socket part is the phone socket on the wall.
The sequence is the following:
Server side:
Socket creation with the socket syscall;
Binding of the port with the bind syscall;
Listening with the listen syscall (this will enable the backlog queue);
Accepting the incoming connections with the accept syscall
This is a blocking operation: your thread will remain blocked until a connection comes in);
The accept function will return a new file descriptor representing the new connection. You will use this one to send/receive data with the other host, while the original file descriptor (from socket) will be used for new incoming connections.
Client side:
Socket creation with socket;
Connection with connect.
Here you may find some additional resources.

Resources