#include #include #include #include #include #include /* For atoi() */ #include /* For toupper() */ #include /* For read() */ /* Same function as we've seen earlier */ int open_listen(int port) { int fd; struct sockaddr_in serverAddr; int optVal; fd = socket(AF_INET, SOCK_STREAM, 0); if(fd < 0) { perror("Error creating socket"); exit(1); } optVal = 1; if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(int)) < 0) { perror("Error setting socket option"); exit(1); } serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(port); serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(fd, (struct sockaddr*)&serverAddr, sizeof(struct sockaddr_in)) < 0){ perror("Error binding socket to port"); exit(1); } if(listen(fd, SOMAXCONN) < 0) { perror("Error listening"); exit(1); } return fd; } /* Same function as we've seen earlier */ char* capitalise(char* buffer, int len) { int i; for(i=0; i= 0; fd--) { /* For each file descriptor- check whether it is set in the readSet ** returned to us */ if(FD_ISSET(fd, &readSet)) { if(fd == fdServer) { /* Listening fd - accept the connection */ fromAddrSize = sizeof(struct sockaddr_in); newFD = accept(fdServer, (struct sockaddr*)&fromAddr, &fromAddrSize); if(newFD < 0) { perror("Error accepting connection"); exit(1); } /* Now have a new fd for a connection from a client - we need ** to add it to our set of fds of interest */ FD_SET(newFD, &baseSet); /* Update max fd if necessary */ if(newFD > maxFD) { maxFD = newFD; } printf("Accepted request from %s, port %d\n", inet_ntoa(fromAddr.sin_addr), ntohs(fromAddr.sin_port)); } else { /* Connected client fd */ /* Data is available (or EOF) - so read data - we can ** guarantee this call won't be blocked */ numBytesRead = read(fd, buffer, 1024); if(numBytesRead > 0) { /* Got some data - capitalise it and send it back */ fflush(stdout); capitalise(buffer, numBytesRead); write(fd, buffer, numBytesRead); } else if(numBytesRead < 0) { perror("Error reading from socket"); exit(1); } else { /* EOF - client has gone away. ** Remove the fd from our set of fds of interest */ FD_CLR(fd, &baseSet); /* Update max FD if necessary - work backwards through ** the set of file descriptors until we get to a fd we're ** interested in */ /* Code here is reason why our outer loop goes backwards ** through the file descriptors */ if(fd == maxFD) { do { maxFD--; } while ( maxFD > 0 && !FD_ISSET(maxFD, &baseSet)); } close(fd); } } } } } } /* Same as single process that we've seen earlier */ int main(int argc, char* argv[]) { int portnum; int fdServer; if(argc != 2) { fprintf(stderr, "Usage: %s port-num\n", argv[0]); exit(1); } portnum = atoi(argv[1]); if(portnum < 1024 || portnum > 65535) { fprintf(stderr, "Invalid port number: %s\n", argv[1]); exit(1); } fdServer = open_listen(portnum); process_connections(fdServer); return 0; }