/* * ISA 563, Spring 2011 * Copyleft by Muhammad Abdulla */ #include #include #include #include #include #include #include #include #include #include #include extern int errno; #define QLEN 20 /* * concurrent-echo-server.c -- demonstrates concurrent server-side processing using fork */ #define PORTNUM 2345 void child_handler(int sig) { pid_t pid; pid = wait(NULL); printf("Child with PID %d exited.\n", pid); } int main ( int argc, char *argv[] ) { int n; int sock, conn; int val; struct sockaddr_in sin ; struct hostent *hen ; char buf[1024]; struct sockaddr_in remote_addr ; socklen_t addr_len ; addr_len = sizeof ( remote_addr ) ; pid_t pid; signal(SIGCHLD, child_handler); // create socket sock = socket ( AF_INET, SOCK_STREAM, 0 ) ; if ( sock < 0 ) { fprintf ( stderr, "Can't create socket: %s\n", strerror(errno) ) ; exit(1) ; } memset ( &sin, 0, sizeof(sin) ) ; sin.sin_family = AF_INET ; sin.sin_addr.s_addr = INADDR_ANY ; sin.sin_port = htons ( (short) PORTNUM ) ; // try to bind to port_num val = bind ( sock, (struct sockaddr *)&sin, sizeof(sin) ) ; if ( val < 0 ) { fprintf ( stderr, "Can't bind socket: %s\n", strerror(errno) ) ; exit(1) ; } // we have to listen for TCP sockets val = listen ( sock, QLEN ) ; if ( val < 0 ) { fprintf ( stderr, "Can't listen on socket: %s\n", strerror(errno) ) ; exit(1) ; } for ( ; ; ) { conn = accept ( sock, (struct sockaddr *)&remote_addr, &addr_len ) ; if (conn == -1) { // accept error if (errno == EINTR) { // caused by an interrupt continue; // try again } else { fprintf(stderr, "%s", strerror(errno)); } } pid = fork(); if ( pid == 0 ) { // child processes the request // first close the listening socket close(sock); while ( (n = read(conn, buf, sizeof(buf))) > 0 ) { write(conn, buf, n); } // done processing request close(conn); exit(0); } // parent is here fprintf(stdout, "Child spawned with pid: %d\n", pid); } close(sock); }