Попытка принять новое соединение с Pthreads с помощью сокетов C - PullRequest
0 голосов
/ 22 октября 2018

Я пытаюсь создать игру «Сапер», в которой несколько игроков могут получить доступ к серверу для игры.Я борюсь с использованием 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);
}
...