// gcc -pthread ... #include #include #include #include #include #include #include #include int skt; // Global. This is the socket that the server will listen on int total_squirrels = 0; void close_server(int signal_number){ printf("Closing down the server\n"); close(skt); } /* The Protocol: * Message type 1: report * 1, then the number of squirrels to report 32-bit int as little endian * Client expects an acknowledgement if the server was listening * * Message type 2: query * 2, then the client expects a response. Response is a message type 3 * * Message type 3: query response * 3, then the number of squirrels so far as a 32-bit little endian integer * * Message type 4: acknowledge report * 4, then nothing more */ void* handle_client(void* arg){ int client_fd = (long int)arg; while(1){ unsigned char type; ssize_t readlen; readlen = read(client_fd, &type, 1); if(readlen != 1) break; if(type == 1){ int new_squirrels; read(client_fd, &new_squirrels, sizeof(new_squirrels)); // should we have used MSG_WAITALL? total_squirrels += new_squirrels; // race condition concern type = 4; write(client_fd, &type, 1); // What if this fails? } else if (type == 2){ type = 3; write(client_fd, &type, 1); write(client_fd, &total_squirrels, sizeof(total_squirrels)); } } close(client_fd); } int main(int argc, char ** argv){ struct sockaddr_in sad; sad.sin_port = htons(5141); sad.sin_addr.s_addr = INADDR_ANY; sad.sin_family = AF_INET; skt = socket(AF_INET, SOCK_STREAM, 0); if(skt == -1){ perror("socket"); return 1; } struct sigaction close_action; close_action.sa_handler = close_server; if(sigaction(SIGINT, &close_action, 0)){ perror("sigaction"); return 1; } if( bind(skt, (struct sockaddr *)(&sad), sizeof(struct sockaddr_in)) ){ perror("bind"); return 1; } if( listen(skt, 5) ){ perror("listen"); return 1; } int client_fd; struct sockaddr_in client_address; socklen_t address_size = sizeof(struct sockaddr_in); for(;;){ client_fd = accept(skt, (struct sockaddr *)(&client_address), &address_size); if(client_fd == -1){ perror("accept"); break; } pthread_t t; pthread_create(&t, 0, handle_client, (void*)(size_t)client_fd); } return 0; }