2015-03-20 2 views
0

У меня возникли проблемы с поиском, как хранить клиентские дескрипторы без блокировки сервера. Я следую модели параллельного сервера, подробно описанной в «Сетевом сетевом интерфейсе» Стивенса.Обработка нескольких клиентов для игрового сервера

Моя программа создает совпадения между игроками.

Структура программы такова: сервер обрабатывает соединения TCP/UDP. Клиентская программа может либо запрашивать, либо подключаться к серверу. Если клиент запрашивает, UDP-сокет обрабатывает запрос, возвращая список ручек уже подключенных клиентов.

Если клиент подключается, сокет TCP обрабатывает соединение на 1. Запрашивает клиента для дескриптора и 2. Хранение их дескриптора. Если есть два клиента, которые подключены, создается отдельный процесс для создания совпадения между ними (но сейчас это не актуально).

В моей программе я мультиплексирую сокет TCP/UDP с select(). Моя текущая проблема заключается в том, как справляться с запросом и хранением клиентских дескрипторов без блокировки.

Я рассмотрел:

  1. создать еще один поток, чтобы иметь дело с просьбой и получать дескриптор клиента.
  2. Сохранение списка подключенных клиентских сокетов и добавление их в структуру данных fd_set и мультиплексирование между ними в дополнение к сокетам TCP/UDP.

  3. Появление другого процесса для обработки запросов/получения ручек, но это не является вероятным, поскольку я храню ручки в структуре данных глобального связанного списка, чтобы сервер мог возвращать список при запросе. Общение с родителями было бы слишком громоздким.

* Код, указанный ниже, еще не был протестирован и является неполным, так как я не понял, как решить эту проблему.

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)) { 

      } 
    } 

ответ

0

Не закрывать tcp_listenfd. Используйте массив TCP-коннекторов, то есть tcp_connfd[10] или что-то еще, а затем подсчитайте количество TCP-кода, которое у вас есть. Для каждого клиента присвойте им новый номер.

Удачи вам!