我正在尝试制作一款《扫雷》,其中多个玩家可以访问服务器来玩游戏。我在努力使用Pthreads允许同时连接多个游戏。该程序以我的main方法启动,然后调用setup_listener,然后调用get_clients。我是pthread和套接字编程的新手,我的理解是,对于每个添加的新客户端,都应该创建一个新线程。 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);
}