Implementation of a Concurrent File Server Using UDP Socket Programming
Implementation of a Concurrent File Server Using UDP Socket Programming
Aim
To implement a concurrent file server using UDP socket programming in C, where multiple clients can request files simultaneously. The server sends the contents of the requested file if it exists; otherwise, it sends an appropriate error message. The server also sends its Process ID (PID) along with the response.
Objectives
After completing this experiment, students should be able to:
- Understand UDP socket programming.
- Learn connectionless communication.
- Understand concurrent server implementation using fork().
- Learn file handling in C.
- Transfer files using UDP sockets.
- Understand Process IDs (PID).
- Handle file-not-found conditions.
Theory
File Server
A File Server is a network application that stores files and supplies them to clients on request.
Whenever a client requests a file,
- the server searches for the file,
- if found, sends the file contents,
- otherwise sends an error message.
File servers are widely used in
- Cloud Storage
- FTP Servers
- Web Servers
- Database Servers
- Network Storage Systems
UDP Socket Programming
UDP (User Datagram Protocol) is a connectionless transport layer protocol.
Unlike TCP,
- no connection establishment is required,
- communication occurs through datagrams,
- lower overhead,
- faster communication.
UDP provides
- low latency
- faster communication
- simple implementation
However,
- packet delivery is not guaranteed,
- packet ordering is not guaranteed,
- no retransmission mechanism exists.
Hence UDP is suitable for lightweight request-response applications.
Concurrent UDP Server
Unlike TCP, UDP does not establish separate client connections.
Whenever a datagram arrives,
the server
- receives the request,
- creates a child process using fork(),
- the child serves that client,
- the parent immediately waits for the next request.
Thus several clients can be served simultaneously.
Process ID (PID)
Every Linux process has a unique Process ID.
The PID is obtained using
getpid();
The child process handling the client's request sends its PID along with the response.
Example
Handled by Server PID : 4821
File Handling Functions
| Function | Purpose |
|---|---|
| fopen() | Opens file |
| fgets() | Reads one line |
| fclose() | Closes file |
| sprintf() | Formats output |
| getpid() | Returns Process ID |
Working Principle
+-------------------------+ | UDP File Server | +------------+------------+ | Receives File Request | fork() +-------------+--------------+ | | Parent Process Child Process Waits for new requests Opens requested file | File Exists ? / \ Yes No | | Read File Contents Error Message | | Attach Process ID (PID) | sendto() Client
Functions Used
| Function | Purpose |
|---|---|
| socket() | Creates UDP socket |
| bind() | Associates socket with port |
| recvfrom() | Receives filename |
| sendto() | Sends response |
| fork() | Creates child process |
| fopen() | Opens file |
| fgets() | Reads file |
| fclose() | Closes file |
| getpid() | Returns PID |
| close() | Closes socket |
Algorithm
Server Algorithm
- Create a UDP socket.
- Bind the socket to port 9000.
- Wait for a filename from the client.
- Receive the filename.
- Create a child process using fork().
-
Child process:
- Obtain its PID.
- Open the requested file.
-
If the file exists:
- Read its contents.
- Attach the PID.
- Send the response to the client.
-
Otherwise:
- Send the PID.
- Send "File Not Found".
- Exit.
- Parent waits for the next client request.
Client Algorithm
- Create UDP socket.
- Enter filename.
- Send filename to server.
- Receive server response.
- Display PID.
- Display file contents.
- Close socket.
Program
UDP Server Program (server.c)
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<arpa/inet.h> #define PORT 9000 #define BUFFER_SIZE 2048 int main() { int sockfd; struct sockaddr_in server,client; socklen_t len=sizeof(client); char filename[100]; char buffer[BUFFER_SIZE]; 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 Concurrent File Server Started\n"); printf(" Listening on Port %d\n",PORT); printf("====================================\n"); while(1) { memset(filename,0,sizeof(filename)); recvfrom(sockfd, filename, sizeof(filename), 0, (struct sockaddr *)&client, &len); if(fork()==0) { FILE *fp; fp=fopen(filename,"r"); memset(buffer,0,sizeof(buffer)); sprintf(buffer, "Handled by Server PID : %d\n\n", getpid()); if(fp==NULL) { strcat(buffer, "Requested File Not Found.\n"); } else { char line[256]; while(fgets(line,sizeof(line),fp)!=NULL) { strcat(buffer,line); } fclose(fp); } sendto(sockfd, buffer, strlen(buffer)+1, 0, (struct sockaddr *)&client, len); printf("Request for %s served by PID %d\n", filename, getpid()); exit(0); } } 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 #define BUFFER_SIZE 2048 int main() { int sockfd; struct sockaddr_in server; socklen_t len=sizeof(server); char filename[100]; char buffer[BUFFER_SIZE]; /* Create UDP Socket */ sockfd=socket(AF_INET,SOCK_DGRAM,0); if(sockfd<0) { printf("Socket Creation Failed\n"); return 0; } /* Server Information */ server.sin_family=AF_INET; server.sin_port=htons(PORT); server.sin_addr.s_addr=inet_addr("127.0.0.1"); /* Get File Name */ printf("Enter File Name : "); scanf("%s",filename); /* Send File Name to Server */ sendto(sockfd, filename, strlen(filename)+1, 0, (struct sockaddr *)&server, len); /* Receive Response */ recvfrom(sockfd, buffer, sizeof(buffer), 0, NULL, NULL); /* Display Response */ printf("\n=====================================\n"); printf("Response Received From Server\n"); printf("=====================================\n\n"); printf("%s\n",buffer); close(sockfd); return 0; }
Compilation
Open a terminal and compile both programs.
gcc server.c -o server gcc client.c -o client
Preparing Sample Files
Create a few text files in the same directory as the server program.
sample1.txt
Government Model Engineering College Department of Computer Engineering Computer Networks Laboratory
sample2.txt
UDP Socket Programming Concurrent File Server Linux Programming
notes.txt
Welcome to the Computer Networks Lab. This experiment demonstrates a concurrent UDP File Server using fork(). Each client request is handled by a separate child process.
Execution Procedure
Step 1
Open Terminal 1.
Run the server.
./server
Step 2
Open Terminal 2.
Run the first client.
./client
Step 3
Enter
sample1.txt
Step 4
Open another terminal.
Run another client.
./client
Enter
sample2.txt
Step 5
Open another terminal.
Run another client.
./client
Enter
abc.txt
where abc.txt does not exist.
Sample Output
Server Terminal
==================================== UDP Concurrent File Server Started Listening on Port 9000 ==================================== Request for sample1.txt served by PID 4213 Request for sample2.txt served by PID 4216 Request for abc.txt served by PID 4219
Observe that every client is served by a different child process, identified by a unique Process ID (PID).
Client 1
Enter File Name : sample1.txt ===================================== Response Received From Server ===================================== Handled by Server PID : 4213 Government Model Engineering College Department of Computer Engineering Computer Networks Laboratory
Client 2
Enter File Name : sample2.txt ===================================== Response Received From Server ===================================== Handled by Server PID : 4216 UDP Socket Programming Concurrent File Server Linux Programming
Client 3
Enter File Name : abc.txt ===================================== Response Received From Server ===================================== Handled by Server PID : 4219 Requested File Not Found.
Program Explanation
Server Program
Step 1
Creates a UDP socket using
socket(AF_INET, SOCK_DGRAM, 0);
Step 2
Binds the socket to Port 9000.
bind(sockfd, (struct sockaddr *)&server, sizeof(server));
Step 3
Waits for a filename from any client.
recvfrom(...)
Step 4
When a filename arrives, the server creates a child process using
fork();
The parent immediately returns to waiting for the next request.
The child serves the current client.
Step 5
The child opens the requested file.
fopen(filename,"r");
Step 6
If the file exists,
the child
-
reads each line using
fgets(), - appends it to the output buffer.
Step 7
The child obtains its Process ID.
getpid();
Step 8
The PID is added to the beginning of the response.
Example
Handled by Server PID : 4213
Step 9
The completed response is sent back using
sendto()
Step 10
The child process terminates.
exit(0);
Client Program
Step 1
Creates a UDP socket.
Step 2
Accepts a filename from the user.
Example
sample1.txt
Step 3
Sends the filename to the server.
sendto()
Step 4
Waits for the server's response.
recvfrom()
Step 5
Displays
- Server PID
- File contents
- Error message (if the file is not found)
Applications
Concurrent file servers are widely used in computer networks and distributed systems. Some important applications include:
- File Sharing Systems
- Cloud Storage Services
- FTP Servers
- Web Servers
- Distributed Computing Systems
- Network Attached Storage (NAS)
- Database Backup Servers
- Software Distribution Servers
- Remote Document Sharing
- Embedded and IoT File Services
Advantages
- Uses UDP, resulting in lower communication overhead.
- Faster communication due to the absence of connection establishment.
- Supports multiple client requests.
- Each client request is handled by a separate child process.
- Easy to understand and implement.
-
Demonstrates process creation using
fork(). - Introduces Process ID (PID) handling.
- Provides practical experience in network file transfer.
- Simple client-server architecture.
- Suitable for undergraduate networking laboratories.
Limitations
- UDP does not guarantee reliable delivery.
- Packets may be lost during transmission.
- Packet ordering is not guaranteed.
- Large files may require fragmentation.
- No retransmission mechanism is provided.
- Suitable only for transferring small text files.
- No client authentication is implemented.
- No encryption or security mechanisms are provided.
Precautions
- Ensure that the server is started before executing the client.
- Store all sample text files in the same directory as the server program.
- Verify that the requested filename is entered correctly.
- Ensure that port 9000 is not being used by another application.
- Use only small text files for this experiment.
- Compile both programs successfully before execution.
- Ensure the client specifies the correct server IP address.
- Close all terminals properly after completing the experiment.
Result
A concurrent File Server application was successfully implemented using UDP socket programming. The server received filename requests from clients, created a child process using the fork() system call to handle each request, and returned either the requested file contents or an appropriate error message along with the child process's Process ID (PID). The experiment demonstrated connectionless communication using UDP, concurrent request handling through process creation, and file transfer over a network.
Comments
Post a Comment