Почему это присвоение дескриптора сокета / файла недопустимо? - PullRequest
0 голосов
/ 19 марта 2012

Я пытаюсь написать простой сервер на c, который играет в игру для двух игроков. Он проверяет наличие входящих подключений и, если нет player1, сохраняет файловый дескриптор player1 (который будет использоваться позже для отправки и получения), и если нет player2, он делает то же самое. У меня есть этот цикл, который я изменил с Здесь . Моя проблема в том, что я хочу получать от одного и отправлять другому, но кажется, что мои назначения недействительны. Когда я пытаюсь отправить на player2, происходит сбой или отправляет мусор. Иногда отправка на player1 отправляет обратно на сервер (?). Правильно ли я использую select и перебираю правильно заданный дескриптор файла? Любые отзывы будут оценены.

// add the listener to the master set
FD_SET(listener, &master);

// keep track of the biggest file descriptor
fdmax = listener; // so far, it's this one

// main loop
while (1) {
    read_fds = master; // copy it
    if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
         error("select");
    }

    // run through the existing connections looking for data to read
    for(i = 0; i <= fdmax; i++) {

        //This indicates that someone is trying to do something
        if (FD_ISSET(i, &read_fds)) {
            if (i == listener) {

                addrlen = sizeof remoteaddr;
                newfd = accept(listener, (struct sockaddr *)&remoteaddr, &addrlen);

                if (newfd == -1) {
                    error("accept");
                } else {
                    FD_SET(newfd, &master);
                    if (newfd > fdmax) {
                        fdmax = newfd;
                    }

                    /* If we have the maximum number of players, we tell if that it's busy */
                    if (players >= 2) {
                         toobusy(fdmax); close(fdmax); FD_CLR(fdmax, &master);
                    }  else {                                                        
                         //Problem here?
                         if (player1_fd == -1) {
                               player1_fd = newfd;                                  
                         }

                         if ((player1_fd != -1) && (player2_fd == -1)) {
                               player2_fd = newfd;                                   
                         }

                         players++;
                         if (players == 2) {
                               sendhandles(); //says two players exist
                         }
                    }
                }
            } else {
                //Possible problems here
                if (i == player1_fd || i == player2_fd) {
                     receive(i); //Processes the messages
                }
            }
        }
    }
}

1 Ответ

0 голосов
/ 19 марта 2012

Часть toobusy должна использовать newfd, а не fdmax.В противном случае в этом коде нет простой ошибки.

Ваш комментарий «Иногда отправка на player1 отправляет обратно на сервер (?)» Заставляет меня думать, что player1_fd и player2_fd могут быть неинициализированы или, возможно, инициализированы в 0 вместо-1.Вы должны дважды проверить, что вы установили их в -1 перед циклом.

Несколько дополнительных примечаний:

  • Вы уверены, что мастер инициализирован 0?Вы вызывали на нем FD_ZERO?
  • Вы должны использовать FD_COPY, чтобы скопировать мастер в read_fds.

Наконец, я бы рекомендовал использовать библиотеку для обработки событий, такую ​​как libevent илиlibev.

...