/* * This is a better server than simple_server.c * I'm only going to comment changes from simple_server.c * So if there's something that doesn't make any sense in here, maybe look at that one. */ #include #include #include #include #include #include #include #include /* server_socket is global, because it's used throughout the file. The server * will only have one server socket, so this should be fine. I did rename it * in this example, it was called "skt" in class. */ int server_socket; /* This server is going to live in an infinite loop. * The expected way to stop it is ctrl+c. * We could also send it a signal using kill. * Either way, there's no place for a shutdown routine unless we include * a signal handler, like the following: */ void shut_down_server(int signal){ printf("\nDoing everything we need to do to shut down the server\n"); /* Depending on the situation, we might have other work to do here: * Deallocate heap-allocated memory * Send clients messages indicating the server is shutting down * Close client sockets * Write final entries to log files, and close the files * Anything else that needs to happen before the server shuts down */ /* Calling close here tells the OS we're done with the socket * If we don't do that, it'll figure it out anyway once we're dead. */ close(server_socket); /* exit will exit the program, and we need it because return would end the * shut_down_server function, not the program itself. 0 is the exit status, * like the thing we return from main normally. 0 indicates there weren't * any problems, everything was fine. */ exit(0); } int main(int argc, char ** argv){ uint16_t listen_port = 5141; // 5141 is the default if(argc > 1){ listen_port = atoi(argv[1]); if(listen_port < 1){ printf("Invalid port: %s\n", argv[1]); exit(1); } printf("Will listen on port %d\n", listen_port); } else { printf("No port specified, defaulting to %d\n", listen_port); } /* Look at "man sigaction" for more on this, but basically, this will register * shut_down_server as the function that will be called when the program receives a * SIGINT (ctrl+c). Normally SIGINT would stop the program running immediately. * Our shut_down_server function calls exit, but if it didn't, the program could * actually survive ctrl+c. */ struct sigaction sa; sa.sa_handler = shut_down_server; sigaction(SIGINT, &sa, 0); struct sockaddr_in sad; sad.sin_port = htons(listen_port); sad.sin_addr.s_addr = INADDR_ANY; sad.sin_family = AF_INET; server_socket = socket(AF_INET, SOCK_STREAM, 0); // Step 1 if(server_socket == -1){ perror("socket"); return 1; } if( bind(server_socket, (struct sockaddr *)(&sad), sizeof(struct sockaddr_in)) ){ // step 2 perror("bind"); return 1; } if( listen(server_socket, 5) ){ // step 3 perror("listen"); return 1; } int client_fd; struct sockaddr_in client_address; socklen_t address_size = sizeof(struct sockaddr_in); while(1){ client_fd = accept(server_socket, (struct sockaddr *)(&client_address), &address_size); // step 4 write(client_fd, "Good Morning", 13); printf("Connection made from address %s\n", inet_ntoa(client_address.sin_addr)); close(client_fd); } // This will never run return 0; }