In previous articles we have seen a TCP server and a UDP server. But now we can combine our concurrent TCP echo server and iterative UDP server into a single server that uses select to multiplex TCP and UDP socket.
Select function is used to select between TCP and UDP socket. This function gives instructions to the kernel to wait for any of the multiple events to occur and awakens the process only after one or more events occur or a specified time passes.
Example – kernel will return only when one of these condition occurs
- Any Descriptor from {1, 2, 3} is ready for reading
- Any Descriptor from {4, 5, 6} is ready for writing
- Time 5sec have passed
The entire process can be broken down into following steps :
Server:
- Create TCP i.e Listening socket
- Create a UDP socket
- Bind both socket to server address.
- Initialize a descriptor set for select and calculate maximum of 2 descriptor for which we will wait
- Call select and get the ready descriptor(TCP or UDP)
- Handle new connection if ready descriptor is of TCP OR receive data gram if ready descriptor is of UDP
UDP Client:
- Create UDP socket.
- Send message to server.
- Wait until response from server is recieved.
- Close socket descriptor and exit.
TCP Client:
- Create a TCP scoket.
- Call connect to establish connection with server
- When the connection is accepted write message to server
- Read response of Server
- Close socket descriptor and exit.
- maxfd: maximum number of descriptor ready.
- timeout: How long to wait for select to return.
-
struct timeval{ long tv_sec; long tv_usec; }; if timeout==NULL then wait forever if timeout == fixed_amount_time then wait until specified time if timeout == 0 return immediately. - readset: Descriptor set that we want kernel to test for reading.
- writeset: Descriptor set that we want kernel to test for writing.
- exceptset: Descriptor set that we want kernel to test for exception conditions.
- sockfd: Descriptor which receives data.
- buff: Application buffer socket descriptor data is copied to this buffer.
- nbytes:Number of bytes to be copied to application buffer.
- Compile the server program (
gcc server.c -o ser) - Run server using (
./ser) - On another terminal, compile tcp client program (
gcc tcp_client.c -o tcpcli) - Run tcp client (
./tcpcli) - On another terminal, compile udp client program (
gcc udp_client.c -o udpcli) - Run udp client (
./udpcli) - Why does DNS use UDP and not TCP?
- Differences between TCP and UDP
- TCP and UDP in Transport Layer
- Various TCP and UDP ports
- TCP with explicit link failure notification (TCP-ELFN)
- UDP Server-Client implementation in C
- TCP Server-Client implementation in C
- TCP Client-Server Program to Check if a Given String is Palindrome
- C program for file Transfer using UDP
- Difference between SCTP and UDP
- Difference between UDP and RTP
- User Datagram Protocol (UDP)
- Services and Segment structure in TCP
- Wrap Around Concept and TCP Sequence Number
- OSI, TCP/IP and Hybrid models
- Difference between TCP and RTP
- TCP/IP Ports and Its Applications
- Difference between SCTP and TCP
- Error Control in TCP
- TCP/IP Model
Necessary functions:
int select(int maxfd, fd_set *readsset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout); Returns: positive count of descriptors ready, 0 on timeout, -1 error
Arguments:
int read(int sockfd, void * buff, size_t nbytes); Returns: number of bytes read from the descriptor. -1 on error
Arguments:
// Server program #include <arpa/inet.h> #include <errno.h> #include <netinet/in.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #define PORT 5000 #define MAXLINE 1024 int max(int x, int y) { if (x > y) return x; else return y; } int main() { int listenfd, connfd, udpfd, nready, maxfdp1; char buffer[MAXLINE]; pid_t childpid; fd_set rset; ssize_t n; socklen_t len; const int on = 1; struct sockaddr_in cliaddr, servaddr; char* message = "Hello Client"; void sig_chld(int); /* create listening TCP socket */ listenfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr;, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(PORT); // binding server addr structure to listenfd bind(listenfd, (struct sockaddr*)&servaddr;, sizeof(servaddr)); listen(listenfd, 10); /* create UDP socket */ udpfd = socket(AF_INET, SOCK_DGRAM, 0); // binding server addr structure to udp sockfd bind(udpfd, (struct sockaddr*)&servaddr;, sizeof(servaddr)); // clear the descriptor set FD_ZERO(&rset;); // get maxfd maxfdp1 = max(listenfd, udpfd) + 1; for (;;) { // set listenfd and udpfd in readset FD_SET(listenfd, &rset;); FD_SET(udpfd, &rset;); // select the ready descriptor nready = select(maxfdp1, &rset;, NULL, NULL, NULL); // if tcp socket is readable then handle // it by accepting the connection if (FD_ISSET(listenfd, &rset;)) { len = sizeof(cliaddr); connfd = accept(listenfd, (struct sockaddr*)&cliaddr;, &len;); if ((childpid = fork()) == 0) { close(listenfd); bzero(buffer, sizeof(buffer)); printf("Message From TCP client: "); read(connfd, buffer, sizeof(buffer)); puts(buffer); write(connfd, (const char*)message, sizeof(buffer)); close(connfd); exit(0); } close(connfd); } // if udp socket is readable receive the message. if (FD_ISSET(udpfd, &rset;)) { len = sizeof(cliaddr); bzero(buffer, sizeof(buffer)); printf("\nMessage from UDP client: "); n = recvfrom(udpfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&cliaddr;, &len;); puts(buffer); sendto(udpfd, (const char*)message, sizeof(buffer), 0, (struct sockaddr*)&cliaddr;, sizeof(cliaddr)); } } } |
TCP_Client.c
// TCP Client program #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #define PORT 5000 #define MAXLINE 1024 int main() { int sockfd; char buffer[MAXLINE]; char* message = "Hello Server"; struct sockaddr_in servaddr; int n, len; // Creating socket file descriptor if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("socket creation failed"); exit(0); } memset(&servaddr;, 0, sizeof(servaddr)); // Filling server information servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (connect(sockfd, (struct sockaddr*)&servaddr;, sizeof(servaddr)) < 0) { printf("\n Error : Connect Failed \n"); } memset(buffer, 0, sizeof(buffer)); strcpy(buffer, "Hello Server"); write(sockfd, buffer, sizeof(buffer)); printf("Message from server: "); read(sockfd, buffer, sizeof(buffer)); puts(buffer); close(sockfd); } |
UDP_client.c
// UDP client program #include <arpa/inet.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <sys/socket.h> #include <sys/types.h> #define PORT 5000 #define MAXLINE 1024 int main() { int sockfd; char buffer[MAXLINE]; char* message = "Hello Server"; struct sockaddr_in servaddr; int n, len; // Creating socket file descriptor if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { printf("socket creation failed"); exit(0); } memset(&servaddr;, 0, sizeof(servaddr)); // Filling server information servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); // send hello message to server sendto(sockfd, (const char*)message, strlen(message), 0, (const struct sockaddr*)&servaddr;, sizeof(servaddr)); // receive server's response printf("Message from server: "); n = recvfrom(sockfd, (char*)buffer, MAXLINE, 0, (struct sockaddr*)&servaddr;, &len;); puts(buffer); close(sockfd); return 0; } |
Steps to compile and run the above codes:
Output of the above codes:



Attention reader! Don’t stop learning now. Get hold of all the important CS Theory concepts for SDE interviews with the CS Theory Course at a student-friendly price and become industry ready.
Recommended Posts:
If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.
Improved By : mohsenfayyaz77

Formed in 2009, the Archive Team (not to be confused with the archive.org Archive-It Team) is a rogue archivist collective dedicated to saving copies of rapidly dying or deleted websites for the sake of history and digital heritage. The group is 100% composed of volunteers and interested parties, and has expanded into a large amount of related projects for saving online and digital history.
