Simple Server With fork() In C++


Server program which I have included in earlier post is really simple one. The main problem associated with that code is; it just accepts one client and serves to it and returns from the program. Generally servers are not like that. The next step of socket programming is that enhance the server to accept multiple client connections and function continuously. Most simplest way to do this is by putting accept (), read () and write () system calls in endless while loop.

while (true)
 {
  iClientStructLength = sizeof(sClientAddress);
  iNewFileDesciptor = accept(iSocketFD, (struct sockaddr*) 
&sClientAddress, &iClientStructLength);
  if(iNewFileDesciptor == -1)
  {
   perror("Error ocurred while accepting the connection!");
   exit(1);
  }
  else
   printf("Client is: %s\n", inet_ntoa(sClientAddress.sin_addr));

  bzero(zBuffer, 256);//Empty the buffer
  int iReadReturn = read(iNewFileDesciptor, zBuffer, 255);
  if(iReadReturn < 0)
  {
   perror("Error ocurred while reading from socket!");
  }
  printf("Simple server received a message: %s\n", zBuffer);
 
  int iWriteReturn = write(iNewFileDesciptor, 
"Hi there, welcome to the simple server", 38);
  if(iWriteReturn < 0)
  {
   perror("Error ocurred while writing to the socket!");
  }
  close(iNewFileDesciptor);
 }

This code segment shows the while loop part of the server which accepts multiple clients. All the other things are same as what I have included in earlier post . If you add this part to your server program and run it with simple client which we have already created you can see that it can accept multiple clients. Wait……There’s a problem..Have you noticed it??? Ok..it can accept multiple clients but servicing to those clients are done as the same order as they have connected. That means if you run the server program and then client program (Client1) (Do not send anything to server) and again client program (Client 2). Client 2 can’t send anything to server until client 1 sends something to server. Reason is that server program stuck in the while loop to complete read and write operations to already accepted client1. So server can’t serves to client2 until it finishes servicing to client1. In order to overcome this issue we can take few approaches. Let’s first see most simple approach of using threads. By using threads we let server program to accept client and assign a new thread to serve to that client until main thread accepting another client or doing some other useful task. In C++ fork() system call can be used to achieve this task. (fork() system call is not something use to create new thread but it creates new child process)

#include <sys/stdio.h> pid_t fork(void);

fork() system call take no arguments and returns the process ID. After calling to fork() both parent and child processes executes the next instruction following the fork call. Therefore we need to distinguish parent and child processes by examining there PID’s.
  • When execuitng fork() if any error occurred then it will return -1.
  • fork() returns 0 to the newly created child process.
  • fork() returns positive value to the parent process.
Following code segment shows how we can use fork() system call in our server program.
while(true)
 {
  iClientStructLength = sizeof(sClientAddress);
  iNewFileDesciptor = accept(iSocketFD, (struct sockaddr*) &sClientAddress, &iClientStructLength);
  if(iNewFileDesciptor == -1)
  {
   perror("Error ocurred while accepting the connection!");
   exit(1);
  }
  else
   printf("Client is: %s\n" ,inet_ntoa(sClientAddress.sin_addr));
  
  if(fork() == 0)
  {
   bzero(zBuffer, 256);
   int iReadReturn = read(iNewFileDesciptor, zBuffer, 255);
   if(iReadReturn < 0)
   {
    perror("Error ocurred while reading from socket!");
   }
   printf("Simple server received a message: %s\n", zBuffer);
 
   int iWriteReturn = write(iNewFileDesciptor, "Hi there, welcome to the simple server", 38);
   if(iWriteReturn < 0)
   {
    perror("Error ocurred while writing to the socket!");
   }
   close(iNewFileDesciptor);
  }
  close(iNewFileDesciptor);
 }
In here we let main program to accept the client connections and create separate child process to each accepted connection to reading and writing. Condition if(fork == 0) checks whether this process is child process and if it is so then let that child process to reading and writing to/from socket. How do we run this program in multiple client mode?
  • Just run server program
  • Run simple client program twice (or as many times as you want)
  • Then type and enter anything in any client
  • Server will reply to that particular client
So there’s no any order of how server serves to the clients. Since each client is servicing through separate process, processing can be done in any order. Complete server program can be found here . Next post will include how we use select() system call to achieve the same result without forking. Have a nice day…

2 comments: