Parallel TCP/IP Socket Server With Multithreading and Multiprocessing in C
Learn how to use the C language to use a TCP/IP server to receive multiple client requests at the same time and run each client request in parallel.
Join the DZone community and get the full member experience.
Join For FreeThe primary intention of writing this article is to give you an overview of how we can entertain multiple client requests to a server in parallel. For example, you are going to create a TCP/IP server which can receive multiple client requests at the same time and entertain each client request in parallel so that no client will have to wait for server time. Normally, you will get lots of examples of TCP/IP servers and client examples online which are not capable of processing multiple client requests in parallel.
In the first example, the TCP/IP server has been designed with multi-threading for parallel processing and in the second example, I have implemented the server with multi-processing to accomplish the same goal.
Below is the server application (in C). Here I have created a function called socketThread
, which is a thread function. Whenever a request comes to the server, the server’s main thread will create a thread and pass the client request to that thread with its ID. The thread will start processing with the client request, generate the report, and send it back to the client. As this is just an example, you need to put your own business logic in the thread function. I have just put a sleep statement here and am sending a hard-coded reply from the server to the client. This is just a very simple example and not a professional based TCP/IP server.
The second program is a sample client to test this server. Both of these programs are for Unix/Linux environments only.
socket_server.c
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include <arpa/inet.h>
#include <fcntl.h> // for open
#include <unistd.h> // for close
#include<pthread.h>
char client_message[2000];
char buffer[1024];
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void * socketThread(void *arg)
{
int newSocket = *((int *)arg);
recv(newSocket , client_message , 2000 , 0);
// Send message to the client socket
pthread_mutex_lock(&lock);
char *message = malloc(sizeof(client_message)+20);
strcpy(message,"Hello Client : ");
strcat(message,client_message);
strcat(message,"\n");
strcpy(buffer,message);
free(message);
pthread_mutex_unlock(&lock);
sleep(1);
send(newSocket,buffer,13,0);
printf("Exit socketThread \n");
close(newSocket);
pthread_exit(NULL);
}
int main(){
int serverSocket, newSocket;
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
//Create the socket.
serverSocket = socket(PF_INET, SOCK_STREAM, 0);
// Configure settings of the server address struct
// Address family = Internet
serverAddr.sin_family = AF_INET;
//Set port number, using htons function to use proper byte order
serverAddr.sin_port = htons(7799);
//Set IP address to localhost
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//Set all bits of the padding field to 0
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
//Bind the address struct to the socket
bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
//Listen on the socket, with 40 max connection requests queued
if(listen(serverSocket,50)==0)
printf("Listening\n");
else
printf("Error\n");
pthread_t tid[60];
int i = 0;
while(1)
{
//Accept call creates a new socket for the incoming connection
addr_size = sizeof serverStorage;
newSocket = accept(serverSocket, (struct sockaddr *) &serverStorage, &addr_size);
//for each client request creates a thread and assign the client request to it to process
//so the main thread can entertain next request
if( pthread_create(&tid[i++], NULL, socketThread, &newSocket) != 0 )
printf("Failed to create thread\n");
if( i >= 50)
{
i = 0;
while(i < 50)
{
pthread_join(tid[i++],NULL);
}
i = 0;
}
}
return 0;
}
This is an example of a simple multithreaded client for testing with 50 parallel requests to the server. If you want to test the client from a different machine, change the localhost to the actual server host and port number.
socket_client.c
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <fcntl.h> // for open
#include <unistd.h> // for close
#include<pthread.h>
void * cientThread(void *arg)
{
printf("In thread\n");
char message[1000];
char buffer[1024];
int clientSocket;
struct sockaddr_in serverAddr;
socklen_t addr_size;
// Create the socket.
clientSocket = socket(PF_INET, SOCK_STREAM, 0);
//Configure settings of the server address
// Address family is Internet
serverAddr.sin_family = AF_INET;
//Set port number, using htons function
serverAddr.sin_port = htons(7799);
//Set IP address to localhost
serverAddr.sin_addr.s_addr = inet_addr("localhost");
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
//Connect the socket to the server using the address
addr_size = sizeof serverAddr;
connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);
strcpy(message,"Hello");
if( send(clientSocket , message , strlen(message) , 0) < 0)
{
printf("Send failed\n");
}
//Read the message from the server into the buffer
if(recv(clientSocket, buffer, 1024, 0) < 0)
{
printf("Receive failed\n");
}
//Print the received message
printf("Data received: %s\n",buffer);
close(clientSocket);
pthread_exit(NULL);
}
int main(){
int i = 0;
pthread_t tid[51];
while(i< 50)
{
if( pthread_create(&tid[i], NULL, cientThread, NULL) != 0 )
printf("Failed to create thread\n");
i++;
}
sleep(20);
i = 0;
while(i< 50)
{
pthread_join(tid[i++],NULL);
printf("%d:\n",i);
}
return 0;
}
Compile both the client and the server in Linux or in Unix like below:
cc socket_client.c -o client -lsocket -lnsl
cc socket_server.c -o server -lsocket –lnsl
First, run the server and then run the client from a different terminal (better to run both from different machines). When you run the client from a different Linux/Unix server, please consider the firewall issues.
Now, below, is the server design with a multi-process approach for parallel processing. Here I am using the same function and calling it from a child process. In the previous example, the same process was called from a child thread.
socket_server.c
// for open
// for close
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void socketThread(int clientSocket)
{
char client_message[2000];
char buffer[1024];
int newSocket = clientSocket;
recv(newSocket , client_message , 2000 , 0);
// Send message to the client socket
pthread_mutex_lock(&lock);
char *message = malloc(sizeof(client_message)+20);
strcpy(message,"Hello Client : ");
strcat(message,client_message);
strcat(message,"\n");
strcpy(buffer,message);
free(message);
pthread_mutex_unlock(&lock);
sleep(1);
send(newSocket,buffer,13,0);
printf("Exit socketThread \n");
close(newSocket);
}
int main(){
int serverSocket, newSocket;
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
pid_t pid[50];
//Create the socket.
serverSocket = socket(PF_INET, SOCK_STREAM, 0);
// Configure settings of the server address struct
// Address family = Internet
serverAddr.sin_family = AF_INET;
//Set port number, using htons function to use proper byte order
serverAddr.sin_port = htons(7799);
//Set IP address to localhost
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
//Set all bits of the padding field to 0
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
//Bind the address struct to the socket
bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
//Listen on the socket, with 40 max connection requests queued
if(listen(serverSocket,50)==0)
printf("Listening\n");
else
printf("Error\n");
pthread_t tid[60];
int i = 0;
while(1)
{
/*---- Accept call creates a new socket for the incoming connection ----*/
addr_size = sizeof serverStorage;
newSocket = (serverSocket, (struct sockaddr *) &serverStorage, &addr_size);
int pid_c = 0;
if ((pid_c = fork())==0)
{
socketThread(newSocket);
}
else
{
pid[i++] = pid_c;
if( i >= 49)
{
i = 0;
while(i < 50)
waitpid(pid[i++], NULL, 0);
i = 0;
}
}
}
return 0;
}
Opinions expressed by DZone contributors are their own.
Comments