#include #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; map animal_counts; uint64_t main_count = 0; void handle_client(int client_fd, struct sockaddr_in client_address){ /* Handle client behavior here */ uint64_t acount; char name_buffer[256]; ssize_t readlen; while(1){ uint8_t type_len; if(read(client_fd, &type_len, 1) != 1) break; if(read(client_fd, name_buffer, type_len) != type_len) break; name_buffer[type_len] = 0; if(read(client_fd, &acount, 8) != 8) break; string name_buffer_string(name_buffer); add_mutex.lock(); if(animal_counts.count(name_buffer_string)) animal_counts[name_buffer_string] += acount; else animal_counts[name_buffer_string] = acount; add_mutex.unlock(); printf("Count for %s is now %lu\n", name_buffer, animal_counts[name_buffer_string]); } /* 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; }