#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; struct version { uint8_t type, major, minor; uint16_t extlen; } __attribute__((packed)); version our_version = {14, 4, 1, 0}; struct game { uint8_t type; uint16_t initial, limit, desclen; char description[30]; } __attribute__((packed)); game our_game = {11, 30, 90, 8, "fun game"}; size_t pieces_write(int fd, void *data, size_t quantity){ for(size_t i = 0; i < quantity; i++){ if(write(fd, (uint8_t*)data + i, 1) != 1) return i; usleep(100000); // 100ms } return quantity; } void handle_client(int client_fd, struct sockaddr_in client_address){ /* Handle client behavior here */ ssize_t readlen; pieces_write(client_fd, &our_version, sizeof(version)); pieces_write(client_fd, &our_game, 15); /* In a moment, we'll read a character */ /* 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; }