// // For each connection , the server will create a thread. // #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include "tcpstream.h" void serve_a_client ( int client_stream_id ); class ClientInfo { public: ClientInfo () {pid_id=0; stream_id=0;} pid_t pid_id; int stream_id; }; static int MAX_NUMBER_CLIENT; static ClientInfo *Client ; main(int argc, char ** argv ) { struct sockaddr_in server_name; struct sockaddr_in client_name; struct hostent *hptr; int client_len; int client_fd; int sd; int port_number ; void signal_catcher(int), reset_proc(int); //------------------------------------------------ // p a r s e a r g u e m e n t //------------------------------------------------ MAX_NUMBER_CLIENT = 5; port_number = 1222; if (argc >= 2 ) port_number = atoi ( argv[1] ); if (argc >= 3 ) MAX_NUMBER_CLIENT = atoi ( argv[2] ); //-------------------------------------------------------- // I N I T I A L I Z A T I O N //-------------------------------------------------------- // seting up the port //-------------------------------------------------------- Client = new ClientInfo[5]; sd = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sd < 0) { perror( "socket fail:" ); exit(1); } server_name.sin_family = AF_INET; server_name.sin_port = htons(port_number); server_name.sin_addr.s_addr = htonl(INADDR_ANY); int tmp= bind (sd, (sockaddr *)&server_name, sizeof (server_name) ) ; if (tmp<0) { perror ("Error, can't bind:" );} //------------------------------------------------------ // M A I N L O O P //------------------------------------------------------ int quit=0; int this_is_main_process = 1; cout << "server is up with port "<< port_number << endl; sigset(SIGCHLD, signal_catcher); // sigset(SIGCHLD, (void *) signal_catcher); signal(SIGHUP, reset_proc); // while (listen ( sd, SOMAXCONN) < 0 ) {cerr<< "ERROR WHEN LISTENING"<< endl;} if (listen ( sd, SOMAXCONN) < 0 ) perror ( "Error in listening:" ); while ( !quit ) { //------------- W A I T I N G F O R C L I E N T ------ client_fd = -1; client_len = sizeof (sockaddr_in); // client_len = sizeof (client_name); while (client_fd<0) { client_fd = accept ( sd, (sockaddr * )&client_name , &client_len ); } //------------- A H... H A V E A C L I E N T ----------- //----------- a t t e m p t o o b t a i n t h e //----------- c l i e n t a d d r e s s //------------------------------------------------------- hptr = gethostbyaddr ( (char *)&(client_name.sin_addr), client_len, PF_INET); cout << " connection from " << inet_ntoa (client_name.sin_addr) << " "; if ( hptr == NULL ) { cout << "can't find host entry " << endl; } else { cout << "client is "<< hptr->h_name << endl; } //------------- G E T A N E M P T Y S L O T -------- int found = -1; for (int g =0; (g< MAX_NUMBER_CLIENT) && (found<0); g++ ) { if (Client[g].pid_id == 0 ) { found = g; } } cout << "empty slot is " << found << endl; if ( found >= 0 ) { Client[found].stream_id = client_fd; Client[found].pid_id = fork(); if ( Client[found].pid_id == 0 ) { int alive = 1; this_is_main_process = 0; setsockopt(client_fd, IPPROTO_TCP, SO_KEEPALIVE, (char *)&alive, (int) sizeof(alive)); serve_a_client(Client[found].stream_id); quit =1; exit(0); } else { close(client_fd); } } else { cout << " total number of client exceeded." << endl; //------- info the client. close (client_fd); } } if (this_is_main_process ) close (sd); } void signal_catcher(int) { int stat_loc; int new_id = wait(&stat_loc); if (WIFEXITED(stat_loc) || WIFSIGNALED(stat_loc)) { for (int id = 0; id < MAX_NUMBER_CLIENT ; id++ ) { if (Client[id].pid_id == new_id) { Client[id].pid_id=0; Client[id].stream_id=0; break; } } } } void reset_proc(int) { for (int id = 0; id < MAX_NUMBER_CLIENT; id ++) { if (Client[id].pid_id != 0) { kill(Client[id].pid_id, SIGINT); wait(NULL); Client[id].pid_id=0; Client[id].stream_id=0; } } }