Я пытаюсь создать игру «Сапер», в которой несколько игроков могут получить доступ к серверу для игры.Я борюсь с использованием Pthreads, чтобы разрешить несколько подключений к игре одновременно.Программа запускается в моем основном методе, затем она вызывает setup_listener, затем вызывает get_clients.Я новичок в программировании pthreads и сокетов, я понимаю, что для каждого нового добавленного клиента должен быть создан новый поток.Метод authenticate_process используется для проверки имени пользователя и пароля клиента.В настоящее время, когда я использую pthread_create, моя игровая логика начинается с функции menu_option, передающей ей текущий сокет клиента.Когда я запускаю свой первый новый клиент, моя программа работает отлично, но как только я запускаю второй клиент, моя программа застревает на холостом ходу.Может ли кто-нибудь показать или объяснить мне, где / что нужно сделать, чтобы решить мою проблему.
/* Global Variables */
int num_conn = 0;
int player_count = 0;
pthread_mutex_t mutexcount;
/*
* Main Program
*/
int main(int argc, char *argv[])
{
int port;
/* Make sure a port was specified. */
if (argc < 2) {
fprintf(stderr,"No port provided using port 12345\n");
port = 12345;
}
else {
port = atoi(argv[1]);
}
int lis_sockfd = setup_listener(port); /* Listener socket. */
pthread_mutex_init(&mutexcount, NULL);
while (1) {
int *cli_sockfd = (int*)malloc(2*sizeof(int)); /* Client sockets */
memset(cli_sockfd, 0, 2*sizeof(int));
/* Get clients connected. */
get_clients(lis_sockfd, cli_sockfd);
pthread_t thread; /* Don't really need the thread id for anything in this case, but here it is anyway. */
int result = pthread_create(&thread, NULL, menu_option, (void *)cli_sockfd); /* Start a new thread for this game. */
if (result){
printf("Thread creation failed with return code %d\n", result);
exit(-1);
}
printf("[DEBUG] New game thread started.\n");
}
close(lis_sockfd);
pthread_mutex_destroy(&mutexcount);
pthread_exit(NULL);
}
/* Sets up the listener socket. */
int setup_listener(int portno)
{
int sockfd;
struct sockaddr_in serv_addr;
/* Get a socket to listen on */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening listener socket.");
/* Zero out the memory for the server information */
memset(&serv_addr, 0, sizeof(serv_addr));
/* set up the server info */
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Bind the server info to the listener socket. */
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR binding listener socket.");
//printf("[DEBUG] Listener set.\n");
/* Return the socket number. */
return sockfd;
}
/* Sets up the client sockets and client connections. */
void get_clients(int lis_sockfd, int * cli_sockfd)
{
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
/* Listen for clients. */
listen(lis_sockfd, 253 - player_count);
/* Zero out memory for the client information. */
memset(&cli_addr, 0, sizeof(cli_addr));
clilen = sizeof(cli_addr);
/* Accept the connection from the client. */
cli_sockfd[num_conn] = accept(lis_sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (cli_sockfd[num_conn] < 0)
/* Horrible things have happened. */
error("ERROR accepting a connection from a client.");
/* Send the client it's ID. */
write(cli_sockfd[num_conn], &num_conn, sizeof(int));
/* Authentication Process */
bool isauthenticated = authenticate_process(*cli_sockfd);
if (isauthenticated){
printf("Authenticated\n");
}
else {
printf("Not Authenticated\n");
}
/* Increment the player count. */
num_conn++;
pthread_mutex_lock(&mutexcount);
player_count++;
printf("Number of players is now %d.\n", player_count);
pthread_mutex_unlock(&mutexcount);
}
/* Runs a game clients. */
void *menu_option(void *thread_data)
{
int *cli_sockfd = (int*)thread_data; /* Client sockets. */
int gameoption = 0;
while(1){
gameoption = recv_int(*cli_sockfd);
printf("[DEBUG] User menu option: %d\n",gameoption);
while (gameoption == 1){
running_game(*cli_sockfd); // Run Game Logic
break;
}
while (gameoption == 2){
show_leaderboard(*cli_sockfd);
// Need to notify client to break and send menu option again
break;
}
}
printf("\nGame over.\n");
close(*cli_sockfd);
free(cli_sockfd);
pthread_exit(NULL);
}