/* Socket Server that does a wait() for a child when it terminates */ /* * An modified example of server using TCP protocol. * (UNIX NETWORK PROGRAMMING, by Richard Stevens, * Prentice Hall, 1990, pp. 284-286) * * The program forks a process for each cli program. * It reads one message from a socket which is connected * with the cli program. It prints out the message on the stderr, * modifies the message, and sends the message back to the cli program. */ #include #include #include #include #include #include #include #include #define period 3 #include "message.h" #define SERV_HOST_ADDR "156.12.127.18" /* pooh's Internet address, defined in /etc/hosts */ extern int *handler(int); main(argc, argv) int argc; char *argv[]; { int sockfd, newsockfd, clilen, pid, err,ok; struct sockaddr_in cli_addr, serv_addr; int SERV_TCP_PORT; char *pname; MES message, tmp; if (signal(SIGCHLD,handler)==SIG_ERR) { perror("Setting Up Signal Catch"); } /* SERV_TCP_PORT is the port number on kiwi used by this server program */ printf("Please input an integer which is larger than 1023.\n"); scanf("%d", &SERV_TCP_PORT); if(SERV_TCP_PORT > 1023) printf("Please run the program cli now.\n"); else { printf("Wrong input.\n"); exit(1); } pname = argv[0]; /* create a socket which is one end of a communication channel */ if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("server: cannot open stream socket"); exit(1); } /* initialize server address */ bzero((char *) &serv_addr, sizeof(serv_addr)); /* reset */ serv_addr.sin_family = AF_INET; /* address family: Internet */ serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); /* accept a connection on any Internet interface */ serv_addr.sin_port = htons(SERV_TCP_PORT); /* specify port number */ /* associate server address with the socket */ if(bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { perror("server: cannot bind local address"); exit(2); } /* specify the queue size of the socket to be 5 */ listen(sockfd, 5); while(1) { clilen = sizeof(cli_addr); /* wait for connection from the cli program. Once connected, */ /* newsockfd is the fd to be used with read() and write() */ ok=0; do { if((newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen)) < 0) { if (errno != EINTR) { perror("server: accept error"); exit(3); } } else ok=1; } while (!ok); if((pid = fork()) < 0) { perror("server: fork"); exit(4); } else if(pid==0) /* child process */ { while(1) { if((err = read(newsockfd, &tmp, sizeof(MES))) == -1) { perror("server: read"); exit(4); } else if (err == 0) exit(5); message.mtype = ntohl(tmp.mtype); message.number = ntohl(tmp.number); fprintf(stderr, "server output: %d %d\n", message.mtype, message.number); tmp.mtype = htonl(message.mtype + 1000); tmp.number = htonl(message.number + 1000); if(write(newsockfd, &tmp, sizeof(MES)) == -1) { perror("server: write"); exit(6); } } } close(newsockfd); /* do nothing else for the parent process */ } } int *handler(sig) int sig; { int result; pid_t pid; fprintf(stderr,"Parent Server: Caught Signal %d\n",sig); pid=wait(&result); fprintf(stderr,"wait() gets pid %d with return code %d\n",pid,result); return(NULL); }