处理游戏服务器的多个客户端

时间:2015-03-20 01:53:33

标签: c tcp network-programming udp multiplexing

我无法确定如何在不阻塞服务器的情况下存储客户端句柄。我正在遵循"套接字网络API"中详述的并发服务器模型。史蒂文斯

我的程序在玩家之间创建了tic tac toe匹配。

程序的结构是这样的:服务器处理两个TCP / UDP连接。客户端程序可以查询或连接到服务器。如果客户端查询,则UDP套接字通过返回已连接客户端的句柄列表来处理查询。

如果客户端连接,则TCP套接字通过1.向客户端请求句柄和2.存储其句柄。如果有两个连接的客户端,则会生成一个单独的进程以在它们之间创建匹配(但现在这不相关)。

在我的程序中,我正在使用select()多路复用TCP / UDP套接字。我目前的问题是如何处理请求和存储客户端句柄而不阻塞。

我考虑过:

  1. 创建另一个线程来处理询问和接收客户端句柄。
  2. 保存连接的客户端套接字列表,并将它们添加到fd_set数据结构中,并在TCP / UDP套接字之间进行多路复用。

  3. 产生另一个处理询问/接收句柄的过程,但这是不可能的,因为我将句柄存储在全局链表数据结构中,以便服务器在查询时可以返回一个列表。回馈父母会过于繁琐。

  4. *下面的代码尚未经过测试,因为我还没有找到解决此问题的方法,因此不完整。

        game_head = NULL; game_tail = game_head;
    
        /* Creating TCP listening socket */
        tcp_listenfd = socket(AF_INET, SOCK_STREAM, 0);
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(TCP_PORT);
        bind(tcp_listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
    
        listen(tcp_listenfd, LISTENQ);
    
        /* Creating UDP socket */
        udpfd = socket(AF_INET, SOCK_DGRAM, 0);
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(UDP_PORT);
        bind(udpfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
    
        /* Signal handling (also possibly handle SIGCHLD)*/
        signal(SIGINT, sighandler);
        signal(SIGUSR2, sighandler);
    
        FD_ZERO(&rset);
        maxfdp1 = max(tcp_listenfd, udpfd) + 1;
        while(1) {
                if (terminate)
                        terminate_program();
                FD_SET(tcp_listenfd, &rset);
                FD_SET(udpfd, &rset);
                if ((nready = select(maxfdp1, &rset, NULL, NULL, NULL)) < 0) {
                        if (errno == EINTR)
                                continue;
                        else
                                perror("select error");
                }
    
                if (FD_ISSET(tcp_listenfd, &rset)) {
                        len = sizeof(cliaddr);
                        tcp_connfd = accept(tcp_listenfd, (struct sockaddr *) &cliaddr, &len);
                        close(tcp_connfd);
                }
    
                if (FD_ISSET(udpfd, &rset)) {
    
                }
        }
    

1 个答案:

答案 0 :(得分:0)

不要关闭tcp_listenfd。使用TCP连接器数组,即tcp_connfd[10]或其他东西,然后计算您拥有的TCP数量。对于每个客户,请为其分配一个新号码。

祝你好运!