I am trying to design an echo server which has concurrently feature. It means, Server for each client, it create a parent and child processes. It is for a game server and each client play separately. I have come up with following code but I have no Idea why each time there is a message from client to server it starts to create a new process and start from
for(;;){ // Run forever
.
As I said I think I must have one process for each client. I expect every process to remain in HandleTCPClient
until client close its socket
Other issue is where can I initial my datas so each children process share it with itself.
#include "wrappers.h" // socket wrapper fns
#include <sys/wait.h> // for waitpid()
#define RCVBUFSIZE 32 // Size of receive buffer
void HandleTCPClient(int ClntSocket);
extern "C" void SigChldHandler( int Signum );
int i = 0;
int main(int argc, char *argv[])
{
int ServSock; // Socket descriptor for server
int ClntSock; // Socket descriptor for client
unsigned short EchoServPort; // Server port
sockaddr_in EchoServAddr; // Local address
sockaddr_in EchoClntAddr; // Client address
pid_t ProcessID; // Process ID from fork()
unsigned int ChildProcCount = 0; // Number of child processes
EchoServPort = SERV_TCP_PORT;; // First arg: local port
// Create socket for incoming connections
ServSock = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
// Construct local address structure
memset((char*)&EchoServAddr, 0, sizeof(EchoServAddr)); /* Zero out structure */
EchoServAddr.sin_family = AF_INET; /* Internet address family */
EchoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
EchoServAddr.sin_port = htons(EchoServPort); /* Local port */
// Bind to the local address
Bind(ServSock, (sockaddr*)&EchoServAddr, sizeof(EchoServAddr));
// Mark the socket so it will listen for incoming connections
Listen(ServSock, 5);
signal(SIGCHLD, SigChldHandler); // for preventing zombies
for(;;){ // Run forever
// Set the size of the in-out parameter
socklen_t ClntLen = sizeof(EchoClntAddr);
// Wait for a client to connect
ClntSock = Accept(ServSock, (sockaddr*) &EchoClntAddr,&ClntLen);
//Startin point of new new player to server
// ClntSock is connected to a client!
printf("Handling client %s\n", inet_ntoa(EchoClntAddr.sin_addr));
// Fork child process and report any errors
if ((ProcessID = fork()) < 0){
perror("fork() failed");
exit(1);
}
if (ProcessID == 0){ // If this is the child process
close(ServSock); // Child closes (deallocates) its parent socket descriptor
HandleTCPClient(ClntSock);
exit(1); // Child process terminates
}
printf("With child process: %d\n", (int)ProcessID);
close(ClntSock); // Parent closes (deallocates) its child socket descriptor
ChildProcCount++; // Increment number of outstanding child processes
}
// NOT REACHED
}
void HandleTCPClient(int ClntSocket){
i++;
cout<<"Start of handling"<<endl;
cout<<"i="<<i<<endl;
char EchoBuffer[RCVBUFSIZE]; // Buffer for echo string
int RecvMsgSize; // Size of received message
// Receive message from client
if((RecvMsgSize = recv(ClntSocket, EchoBuffer, RCVBUFSIZE, 0)) < 0){
perror("recv() failed"); exit(1);
cout<<"Error"<<endl;
}
// Send received string and receive again until end of transmission
while(RecvMsgSize > 0){ // zero indicates end of transmission
// Echo message back to client
if(send(ClntSocket, EchoBuffer, RecvMsgSize, 0) != RecvMsgSize){
cout<<"Error"<<endl;
perror("send() failed"); exit(1);
}
// See if there is more data to receive
if((RecvMsgSize = recv(ClntSocket, EchoBuffer, RCVBUFSIZE, 0)) < 0){
cout<<"Error"<<endl;
perror("recv() failed"); exit(1);
}
}
close(ClntSocket); /* Close client socket */
cout<<"End of handling"<<endl;
}
extern "C" void SigChldHandler( int Signum ){
// Catch SIGCHLD signals so child processes don't become zombies.
pid_t pid;
int stat;
while((pid = waitpid(-1, &stat, WNOHANG)) > 0 );
return;
}
Output for three messages form client to server:
Handling client 127.0.0.1
With child process: 40830
Start of handling
i=1
Handling client 127.0.0.1
With child process: 40831
Start of handling
i=1
Handling client 127.0.0.1
With child process: 40832
Start of handling
i=1
Handling client 127.0.0.1
With child process: 40833
Start of handling
i=1
End of handling
End of handling
End of handling
End of handling
As you can see it creates three processes and when I close the program it will close socket for each process!!!
> Edit2 Client side is abstracted:
int main()
{
int Sockfd;
sockaddr_in ServAddr;
char ServHost[] = "localhost";
hostent *HostPtr;
int Port = SERV_TCP_PORT;
//int BuffSize = 0;
//Connection
// get the address of the host
HostPtr = Gethostbyname(ServHost);
if(HostPtr->h_addrtype != AF_INET){
perror("Unknown address type!");
exit(1);
}
memset((char *) &ServAddr, 0, sizeof(ServAddr));
ServAddr.sin_family = AF_INET;
ServAddr.sin_addr.s_addr = ((in_addr*)HostPtr->h_addr_list[0])->s_addr;
ServAddr.sin_port = htons(Port);
//Do some operation
while(!loop){
// open a TCP socket
Sockfd = Socket(AF_INET, SOCK_STREAM, 0);
// connect to the server
Connect(Sockfd, (sockaddr*)&ServAddr, sizeof(ServAddr));
//Prepare message to send server
// write a message to the server
write(Sockfd, data, sizeof(data));
int Len = read(Sockfd, data, 522);
//work on the message from server
}
close(Sockfd);
}