У меня возникли проблемы с поиском, как хранить клиентские дескрипторы без блокировки сервера. Я следую модели параллельного сервера, подробно описанной в «Сетевом сетевом интерфейсе» Стивенса.Обработка нескольких клиентов для игрового сервера
Моя программа создает совпадения между игроками.
Структура программы такова: сервер обрабатывает соединения TCP/UDP. Клиентская программа может либо запрашивать, либо подключаться к серверу. Если клиент запрашивает, UDP-сокет обрабатывает запрос, возвращая список ручек уже подключенных клиентов.
Если клиент подключается, сокет TCP обрабатывает соединение на 1. Запрашивает клиента для дескриптора и 2. Хранение их дескриптора. Если есть два клиента, которые подключены, создается отдельный процесс для создания совпадения между ними (но сейчас это не актуально).
В моей программе я мультиплексирую сокет TCP/UDP с select()
. Моя текущая проблема заключается в том, как справляться с запросом и хранением клиентских дескрипторов без блокировки.
Я рассмотрел:
- создать еще один поток, чтобы иметь дело с просьбой и получать дескриптор клиента.
Сохранение списка подключенных клиентских сокетов и добавление их в структуру данных fd_set и мультиплексирование между ними в дополнение к сокетам TCP/UDP.
Появление другого процесса для обработки запросов/получения ручек, но это не является вероятным, поскольку я храню ручки в структуре данных глобального связанного списка, чтобы сервер мог возвращать список при запросе. Общение с родителями было бы слишком громоздким.
* Код, указанный ниже, еще не был протестирован и является неполным, так как я не понял, как решить эту проблему.
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)) {
}
}