Today we will discuss about tcp server which will be serving more clients at one time . Usually we do use simple echo server one client at a time . In Unix operating systems we can easily creates multiple client handling server even-though so many advanced options out there. In fork system call will help us to achieve this. check out the following code
/*
* server.cpp
*
* Created on: Nov 26, 2011
* Author: srijeyanthan
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
void str_echo(int sockfd);
using namespace std;
int main(int argc, char **argv) {
pid_t childid;
sockaddr_in serveraddr, clientaddr;
socklen_t clilen;
int listnfd, clientfd;
listnfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(9999);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(listnfd, (struct sockaddr*) &serveraddr, sizeof(serveraddr));
listen(listnfd, 7);
for (;;) {
clilen = sizeof(clientaddr);
cout <<"intial client len ::"<<clilen<<endl;
clientfd = accept(listnfd, (struct sockaddr*) &clientaddr, &clilen);
if ((childid = fork()) == 0) {
close(listnfd);
str_echo(clientfd);
cout <<"echoed successfully.."<<endl;
exit(0);
}
close(clientfd);
}
return 0;
}
void str_echo(int sockfd) {
ssize_t n;
char buf[1024];
again: while ((n = read(sockfd, buf, 1024)) > 0)
write(sockfd, buf, n);
if (n < 0 && errno == EINTR)
goto again;
else if (n < 0)
cout<<"str_echo: read error"<<endl;
}
/*
* server.cpp
*
* Created on: Nov 26, 2011
* Author: srijeyanthan
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <iostream>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
void str_echo(int sockfd);
using namespace std;
int main(int argc, char **argv) {
pid_t childid;
sockaddr_in serveraddr, clientaddr;
socklen_t clilen;
int listnfd, clientfd;
listnfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(9999);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(listnfd, (struct sockaddr*) &serveraddr, sizeof(serveraddr));
listen(listnfd, 7);
for (;;) {
clilen = sizeof(clientaddr);
cout <<"intial client len ::"<<clilen<<endl;
clientfd = accept(listnfd, (struct sockaddr*) &clientaddr, &clilen);
if ((childid = fork()) == 0) {
close(listnfd);
str_echo(clientfd);
cout <<"echoed successfully.."<<endl;
exit(0);
}
close(clientfd);
}
return 0;
}
void str_echo(int sockfd) {
ssize_t n;
char buf[1024];
again: while ((n = read(sockfd, buf, 1024)) > 0)
write(sockfd, buf, n);
if (n < 0 && errno == EINTR)
goto again;
else if (n < 0)
cout<<"str_echo: read error"<<endl;
}
you guys might be knowing common steps of socket creation binding and listing . accept system call is blocking , So it will return client connection ID when client is successfully handshake . The above code has explained , whenever new client arrives we are spawning new client and client specific process will be handled by that particular process . Main drawback of this method would be every client we have to spawn new process which will end up with so many resource consuming in kernel level . For small number of clients we can use this method very efficiently.