/* * 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. Also, it uses a select statement to choose between read() and recv(). This is because it is upgraded to be able to receive out of band data. */ #include #include #include #include #include #include #include #include #include "message.h" #define SERV_HOST_ADDR "156.12.127.18" /* acad's Internet address, defined in /etc/hosts */ extern int errno; main(argc, argv) int argc; char *argv[]; { int sockfd, newsockfd, clilen, pid, err,OOB_fd; struct sockaddr_in cli_addr, serv_addr; int SERV_TCP_PORT; fd_set fds; char *pname; MES message, tmp; /* 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_DGRAM, 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); } OOB_fd=dup(sockfd); while(1) { FD_ZERO(&fds); FD_SET(OOB_fd,&fds); FD_SET(sockfd,&fds); clilen = sizeof(cli_addr); bzero((char *) &cli_addr, sizeof(cli_addr)); /* reset */ select(10,&fds,NULL,NULL,NULL); if (FD_ISSET(sockfd,&fds)) { /* if((err = recvfrom(sockfd, &tmp, sizeof(MES),0, &cli_addr,sizeof(cli_addr))) == -1){ */ if((err = recv(sockfd, &tmp, sizeof(MES),0))==-1) { perror("server: ordinary 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); } if (FD_ISSET(OOB_fd,&fds)) { /* Get out of band data */ /* if ((err=recvfrom(sockfd,&tmp,sizeof(MES),MSG_OOB, (struct sockaddr *) &cli_addr,sizeof(cli_addr)))==-1) { */ if ((err=recv(sockfd,&tmp,sizeof(MES),MSG_OOB))==-1) { perror("server: read out of band"); exit(4); } /* Print it out */ message.mtype = ntohl(tmp.mtype); message.number = ntohl(tmp.number); fprintf(stderr, "server OOB 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); } */ } }