ccplusplus.com
Learn C, C++ Concepts
Monday, September 5, 2011
socket wait and waitpid function
/* rpnsrv.c— RPN server shows using the waitpid function * * Example RPN Server: */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <time.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <sys/wait.h> #include <signal.h> #ifndef SHUT_RDWR #define SHUT_RDWR 3 #endif extern int mkaddr(void *addr, int *addr_len, char *input_address, char *protocol); extern void rpn_process(FILE *tx, char *buf); /* * Process Terminated Child processes: */ static void sigchld_handler(int signo) { pid_t PID; int status; do { /* * see the usage of waitpid(2) function call * waitpid(2) until no more exit status information is available. */ PID = waitpid(-1,&status,WNOHANG); } while ( PID != -1 ); /* * Re-instate handler */ signal(SIGCHLD,sigchld_handler); } /* * This function reports the error and * exits back to the shell: */ static void displayError(const char *on_what) { if ( errno != 0 ) { fputs(strerror(errno),stderr); fputs(": ",stderr); } fputs(on_what,stderr); fputc('\n' ,stderr); exit(1); } int main(int argc,char **argv) { int z; char *srvr_addr = "127.0.0.:9090"; struct sockaddr_in adr_srvr; /* AF_INET */ struct sockaddr_in adr_clnt; /* AF_INET */ int len_inet; /* length */ int s = -1; /* Socket */ int c = -1; /* Client socket */ FILE *rx = NULL; /* Read stream */ FILE *tx = NULL; /* Write stream */ char buf[4096]; /* I/O Buffer */ pid_t PID; /* Process ID */ /* * Set signal handler for SIGCHLD: */ signal(SIGCHLD,sigchld_handler); /* * Use a server address from the command * line, otherwise default to 127.0.0.: */ if ( argc >= 2 ) { srvr_addr = argv[1]; } len_inet = sizeof adr_srvr; z = mkaddr(&adr_srvr, &len_inet, srvr_addr, "tcp"); if ( z < 0 || !adr_srvr.sin_port ) { fprintf(stderr, "Invalid server " "address, or no port number " "was specified.\n"); exit(1); } /* * Create a TCP/IP socket to use: */ s = socket(PF_INET,SOCK_STREAM,0); if ( s == -1 ) { displayError("socket(2)"); } /* * Bind the server address: */ z = bind(s, (struct sockaddr *)&adr_srvr, len_inet); if ( z == -1 ) { displayError("bind(2)"); } /* * Make it a listening socket: */ z = listen(s,10); if ( z == -1 ) { displayError("listen(2)"); } /* * Start the server loop: */ for (;;) { /* * Wait for a connect: */ len_inet = sizeof adr_clnt; c = accept(s, (struct sockaddr *)&adr_clnt, &len_inet); if ( c == - ) { displayError("accept(2)"); } /* * Fork a new server process * to service this client: */ if ( (PID = fork()) == -1 ) { /* Failed to fork: Give up */ close(c); continue; } else if ( PID > 0 ) { /* Parent process: */ close(c); continue; } /* * CHILD PROCESS: * Create streams: */ rx = fdopen(c,"r"); if ( !rx ) { /* Failed */ close(c); continue; } tx = fdopen(dup(c),"w"); if ( !tx ) { fclose(rx); continue; } /* * Set both streams to line * buffered mode: */ setlinebuf(rx); setlinebuf(tx); /* * Process client's requests: */ while ( fgets(buf,sizeof buf,rx) ) rpn_process(tx,buf); /* * Close this client's connection: */ fclose(tx); shutdown(fileno(rx),SHUT_RDWR); fclose(rx); /* * Child process must exit: */ exit(0); } /* Control never gets here */ return 0; }
No comments:
Post a Comment
Newer Post
Older Post
Home
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment