#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; void handle_client(int client_fd, struct sockaddr_in client_address); struct client_info { thread client_thread; int client_fd; struct sockaddr_in client_address; bool active = true; client_info(int cfd, struct sockaddr_in ca) : client_fd(cfd), client_address(ca), client_thread(handle_client, cfd, ca) {} }; vector client_list; mutex client_list_mutex; mutex add_mutex; uint64_t main_count = 0; void handle_client(int client_fd, struct sockaddr_in client_address){ /* Handle client behavior here */ uint64_t client_addition; while(1){ ssize_t readlen = read(client_fd, &client_addition, sizeof(uint64_t)); // reads up to 4 bytes if(readlen != 8) // We got the wrong amount of data! break; add_mutex.lock(); main_count += client_addition; add_mutex.unlock(); printf("Main count is now %lu\n", main_count); write(client_fd, &main_count, sizeof(uint64_t)); } /* This part is related to disconnection. Applies broadly. */ client_list_mutex.lock(); for(int i = 0; i < client_list.size(); i++) if(client_list[i].client_fd == client_fd){ client_list[i].active = false; break; } client_list_mutex.unlock(); close(client_fd); } /* We need a cleanup routine */ void cleanup(){ for(;;){ client_list_mutex.lock(); for(int i = 0; i < client_list.size(); i++) if(!client_list[i].active) { client_list[i].client_thread.join(); client_list.erase(client_list.begin() + i); } client_list_mutex.unlock(); sleep(1); } } int main(int argc, char ** argv){ uint16_t port = 5143; struct sockaddr_in sad; sad.sin_port = htons(port); sad.sin_addr.s_addr = INADDR_ANY; sad.sin_family = AF_INET; int skt = socket(AF_INET, SOCK_STREAM, 0); // Step 1 if(skt == -1){ perror("socket"); return 1; } while( bind(skt, (struct sockaddr*)(&sad), sizeof(struct sockaddr_in)) ){ // step 2 perror("bind"); port += 1; sad.sin_port = htons(port); if(port > 5150) return 1; printf("Trying port %d\n", port); } if( listen(skt, 5) ){ // step 3 perror("listen"); return 1; } thread cleanup_thread(cleanup); /* This loop will accept clients onto the server. Each client will have a file descriptor */ while(1){ int client_fd; struct sockaddr_in client_address; socklen_t address_size = sizeof(struct sockaddr_in); client_fd = accept(skt, (struct sockaddr *)(&client_address), &address_size); // step 4 printf("Connection made from address %s\n", inet_ntoa(client_address.sin_addr)); /* Start a thread to handle this client */ client_list_mutex.lock(); client_list.push_back(client_info(client_fd, client_address)); client_list_mutex.unlock(); } return 0; }