Most services work connection-oriented, but some are based on using datagram sockets and work connectionless.
The server uses the following socket or POSIX interface functions in the example programs:
socket(): create a socket
bind(): assign a name to a socket
recvfrom(): read a message from a socket
close(): close a socket
The program is shown in two variants:
In example 1, the program terminates after reading a message.
In example 2, after reading a message, the program waits in an endless loop for more messages.
Example 1: connectionless server without a program loop
#include <stdio.h> #include <sys/socket.h> #include <ioctl.h> #include <signal.h> #include <netinet/in.h> #include <netdb.h> #define ERROR_EXIT(M) perror(M); exit(1) #define TESTPORT 2222 int main(int argv, char **argv) { int sock; int length; struct sockaddr_in server; char buf[1024]; /* Create the socket to be read from. */ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { ERROR_EXIT("socket"); } /* Assign a name to the socket using wildcards */ server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(TESTPORT); if (bind(sock, (struct sockaddr *)&server, sizeof server ) < 0) { ERROR_EXIT("bind"); } /* Read from the server */ length = sizeof(server); memset(buf,0,sizeof(buf)); if (recvfrom(sock, buf, 1024, 0, (struct sockaddr *)&server, &length) < 0) { ERROR_EXIT("recvfrom"); } else { printf("->%s\n",buf); } close(sock); return 0; }
Example 2: connectionless server with a program loop
Since this program runs in an endless loop, the socket is never explicitly closed. However, all sockets are closed automatically if the process is cancelled or reaches its normal end.
#include <sys/socket.h> #include <ioctl.h> #include <signal.h> #include <netinet/in.h> #include <netdb.h> #include <stdio.h> #define ERROR_EXIT(M) perror(M); exit(1) #define TESTPORT 2222 int main(int argc, char **argv) { int sock; int length; struct sockaddr_in server; char buf[1024]; /* Create the socket to be read from. */ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { ERROR_EXIT("socket"); } /* Assign a name to the socket using wildcards */ server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(TESTPORT); if (bind(sock, (struct sockaddr *)&server, sizeof server ) < 0) { ERROR_EXIT("bind"); } /* Start reading from the server */ length = sizeof(server); for (;;) { memset(buf,0,sizeof(buf)); if (recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&server, &length) < 0) { ERROR_EXIT("recvfrom"); } else { printf("->%s\n",buf); } } /* NOTREACHED */ }
The following steps are executed in the program:
The socket() function creates a communication endpoint (server socket) and the associated descriptor.
- The bind() function assigns a defined port number to the server socket so that it can be addressed from the network via this port number.
The recvfrom() function is used to read from a socket of the SOCK_DGRAM type. The result is the length of the read message.
If there is no message, the process is blocked until a message arrives.
The example programs are only valid for the communications domain AF_INET. If they are modified according to the information in "Socket addressing" and "Creating a socket", they are also valid for the AF_INET6 domain.