/* ** Program which listens on a port for incoming connections. Multiple ** simultaneous incoming connections are supported. Data received over each ** connection is converted to upper case and returned. */ #include #include #include #include #include #include /* For atoi() */ #include /* For toupper() */ #include /* For read() */ int open_listen(int port) { int fd; struct sockaddr_in serverAddr; /* Create TCP socket */ fd = socket(AF_INET, SOCK_STREAM, 0); if(fd < 0) { perror("Error creating socket"); exit(1); } /* Server address that we'll listen on - any interface (IP Address) and ** the given port */ serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(port); serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Bind to the port */ if(bind(fd, (struct sockaddr*)&serverAddr, sizeof(struct sockaddr_in)) <0) { perror("Error binding socket to port"); exit(1); } /* Listen for incoming connections */ if(listen(fd, SOMAXCONN) < 0) { perror("Error listening"); exit(1); } return fd; } char* capitalise(char* buffer, int len) { int i; for(i=0; i= 0; fd--) { if(FD_ISSET(fd, &readSet)) { if(fd == fdServer) { /* Listening socket had an event - connection ready - ** accept it */ fromAddrSize = sizeof(struct sockaddr_in); newFD = accept(fdServer, (struct sockaddr*)&fromAddr, &fromAddrSize); if(newFD < 0) { perror("Error accepting connection"); exit(1); } /* Add new fd to our base set so we'll check it for events */ FD_SET(newFD, &baseSet); /* Adjust max fd if necessary */ if(newFD > maxFD) { maxFD = newFD; } fprintf(stderr, "Accepted request from %s, port %d. (FD=%d)\n", inet_ntoa(fromAddr.sin_addr), ntohs(fromAddr.sin_port), newFD); } else { /* One of the client fd's was readable - read data ** from it */ numBytesRead = read(fd, buffer, 1024); if(numBytesRead > 0) { capitalise(buffer, numBytesRead); write(fd, buffer, numBytesRead); } else if(numBytesRead < 0) { perror("Error reading from socket"); exit(1); } else { /* EOF on client fd - close connection - remove ** it from our base set of fds */ fprintf(stderr,"FD %d closed\n", fd); FD_CLR(fd, &baseSet); if(fd == maxFD) { /* Adjust our max FD down as appropriate */ do { maxFD--; } while (!FD_ISSET(maxFD, &baseSet)); } close(fd); } } } } } } 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; }