Implementation of a Concurrent Time Server Using UDP Socket Programming
Implementation of a Concurrent Time Server Using UDP Socket Programming
Aim
To implement a concurrent Time Server application using UDP socket programming in C, where the client sends a time request to a remote server, the server retrieves its current system time, and sends the time back to the client for display.
Objectives
After completing this experiment, students should be able to:
- Understand the working of the User Datagram Protocol (UDP).
- Learn UDP client-server socket programming.
- Understand connectionless communication.
- Learn how to obtain the system time in Linux using C library functions.
- Implement a request-response application using UDP sockets.
- Understand how a UDP server can serve multiple clients concurrently.
Theory
User Datagram Protocol (UDP)
The User Datagram Protocol (UDP) is one of the core transport layer protocols in the TCP/IP protocol suite. Unlike TCP, UDP is a connectionless protocol, meaning that no connection is established before data transmission.
UDP simply sends packets called datagrams from one host to another without checking whether the receiver is ready.
UDP provides:
- Low communication overhead
- Faster transmission
- Simple protocol implementation
- No connection establishment delay
However, UDP does not provide:
- Reliable delivery
- Packet sequencing
- Flow control
- Congestion control
- Error recovery
Because of these characteristics, UDP is widely used in applications where speed is more important than reliability.
Examples include:
- DNS
- DHCP
- Online gaming
- Audio streaming
- Video conferencing
- Network Time Protocol (NTP)
Time Server
A Time Server is a server application that provides the current date and time to clients connected over a network.
Whenever a client sends a request,
- the server receives the request,
- obtains the current system time,
- converts it into a readable format,
- sends the formatted time string back to the client.
The client simply displays the received time.
Concurrent UDP Server
Since UDP is a connectionless protocol, the server does not maintain separate connections for each client.
Each client request is processed independently.
Therefore, multiple clients can send requests simultaneously, and the server responds to each request individually.
This makes UDP servers naturally suitable for simple concurrent request-response applications.
Working Principle
+-----------------------+ | UDP Server | | Waits for Requests | +-----------+-----------+ | ----------------------------------------------- | | | Client 1 Client 2 Client 3 | | | ----------- Time Request (UDP) --------------- | Current System Time | ----------- Time Response (UDP) --------------
Functions Used
| Function | Description |
|---|---|
| socket() | Creates a UDP socket |
| bind() | Associates socket with IP address and port |
| sendto() | Sends data to the client |
| recvfrom() | Receives data from the client |
| time() | Returns the current system time |
| ctime() | Converts time into readable string |
| close() | Closes the socket |
Algorithm
Server Algorithm
- Create a UDP socket.
- Bind the socket to port number 9000.
- Display that the server has started.
-
Wait for a client request using
recvfrom(). - Receive the request message.
-
Obtain the current system time using the
time()function. -
Convert the time into a human-readable string using
ctime(). -
Send the formatted time string to the requesting client using
sendto(). - Continue waiting for further client requests.
Client Algorithm
- Create a UDP socket.
- Specify the server IP address and port number.
- Send a request message ("TIME") to the server.
- Wait for the server's response.
- Receive the current system time.
- Display the received time.
- Close the socket.
Program
Server Program (server.c)
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<arpa/inet.h> #include<time.h> #define PORT 9000 int main() { int sockfd; char buffer[100]; struct sockaddr_in server,client; socklen_t len=sizeof(client); sockfd=socket(AF_INET,SOCK_DGRAM,0); server.sin_family=AF_INET; server.sin_addr.s_addr=INADDR_ANY; server.sin_port=htons(PORT); bind(sockfd,(struct sockaddr *)&server,sizeof(server)); printf("=====================================\n"); printf(" UDP Time Server Started\n"); printf(" Listening on Port %d\n",PORT); printf("=====================================\n"); while(1) { recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client, &len); time_t currentTime; time(¤tTime); char *timeString=ctime(¤tTime); sendto(sockfd, timeString, strlen(timeString)+1, 0, (struct sockaddr *)&client, len); printf("Time request served.\n"); } close(sockfd); return 0; }
Client Program (client.c)
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<arpa/inet.h> #define PORT 9000 int main() { int sockfd; char buffer[100]; struct sockaddr_in server; socklen_t len=sizeof(server); sockfd=socket(AF_INET,SOCK_DGRAM,0); server.sin_family=AF_INET; server.sin_port=htons(PORT); server.sin_addr.s_addr=inet_addr("127.0.0.1"); strcpy(buffer,"TIME"); sendto(sockfd, buffer, strlen(buffer)+1, 0, (struct sockaddr *)&server, len); recvfrom(sockfd, buffer, sizeof(buffer), 0, NULL, NULL); printf("\nCurrent Server Time\n"); printf("%s\n",buffer); close(sockfd); return 0; }
Compilation
gcc server.c -o server gcc client.c -o client
Execution
Open two terminals.
Terminal 1
./server
Terminal 2
./client
To demonstrate concurrency, open additional client terminals and execute:
./client
Each client independently requests the current time from the server.
Sample Output
Server Terminal
===================================== UDP Time Server Started Listening on Port 9000 ===================================== Time request served. Time request served. Time request served.
Client Terminal 1
Current Server Time Thu Jul 30 14:20:18 2026
Client Terminal 2
Current Server Time Thu Jul 30 14:20:23 2026
Client Terminal 3
Current Server Time Thu Jul 30 14:20:30 2026
Program Explanation
Server
-
Creates a UDP socket using the
socket()system call. -
Binds the socket to port 9000 using
bind(). -
Waits continuously for client requests using
recvfrom(). -
When a request is received, the server calls the
time()function to obtain the current system time. -
The
ctime()function converts the time into a human-readable string. -
The server sends the formatted time string back to the requesting client using
sendto(). - The server continues running indefinitely, serving requests from multiple clients without establishing dedicated connections.
Client
- Creates a UDP socket.
- Specifies the server's IP address and port number.
-
Sends the request message "TIME" to the server using
sendto(). -
Waits for the server's response using
recvfrom(). - Displays the received date and time.
- Closes the socket and terminates.
Applications
- Network Time Protocol (NTP)
- Time Synchronization Services
- Distributed Computing Systems
- Network Monitoring Tools
- Logging and Audit Systems
- IoT Devices
- Embedded Systems
Advantages
- Simple implementation.
- Faster communication than TCP.
- Low protocol overhead.
- No connection establishment delay.
- Suitable for lightweight request-response services.
- Can handle multiple client requests efficiently.
Limitations
- No guaranteed packet delivery.
- Packets may be lost.
- No acknowledgement mechanism.
- No flow control or congestion control.
- Not suitable for applications requiring reliable communication.
Result
A concurrent Time Server application was successfully implemented using UDP socket programming. The client sent a time request to the server, the server retrieved its current system time, transmitted it back to the client, and the client displayed the received time correctly. The experiment demonstrated the implementation of a connectionless request-response service using UDP and illustrated how a UDP server can efficiently serve multiple client requests.
Comments
Post a Comment