поведение select () для возможности записи? - PullRequest
2 голосов
/ 21 мая 2011

У меня есть fd_set "write_set", который содержит сокеты, которые я хочу использовать в вызове send (...).Когда я вызываю select (maxsockfd + 1, NULL, & write_set, NULL и & tv), он всегда возвращает 0 (тайм-аут), хотя я еще ничего не отправлял через сокеты в write_set, и должна быть возможность отправки данных.

Почему это?Не следует ли выбрать возврат сразу, когда можно отправить данные через сокеты в write_set?

Спасибо!

Редактировать: Мой код ..

// _read_set and _write_set are the master sets
fd_set read_set = _read_set;
fd_set write_set = _write_set;

// added this for testing, the socket is a member of RemoteChannelConnector.
std::list<RemoteChannelConnector*>::iterator iter;
for (iter = _acceptingConnectorList->begin(); iter != _acceptingConnectorList->end(); iter++) {

    if(FD_ISSET((*iter)->getSocket(), &write_set)) {

        char* buf = "a";
        int ret;
        if ((ret = send((*iter)->getSocket(), buf, 1, NULL)) == -1) {
            std::cout << "error." << std::endl;
        } else {
            std::cout << "success." << std::endl;
        }

    }

}

struct timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 0;

int status;

if ((status = select(_maxsockfd, &read_set, &write_set, NULL, &tv)) == -1) {

    // Terminate process on error.
    exit(1);

} else if (status == 0) {

    // Terminate process on timeout.
    exit(1);

} else {
// call send/receive
}

Когда я запускаюэто с кодом для тестирования, если мой сокет на самом деле находится в write_set и если есть возможность отправить данные через сокет, я получаю "успех" ...

Ответы [ 2 ]

0 голосов
/ 21 июня 2011

Ваш код очень запутан. Во-первых, вы, похоже, не устанавливаете ни одного из битов в fd_set. Во-вторых, вы проверяете биты еще до того, как позвоните select.

Вот как обычно работает поток ...

  • Используйте FD_ZERO для обнуления вашего набора.
  • Пройдите, и для каждого дескриптора файла, который вас интересует в состоянии записи, используйте FD_SET для его установки.
  • Вызовите select, передав ему адрес fd_set, для которого вы вызывали функцию FD_SET для набора записи, и просмотрите возвращаемое значение.
  • Если возвращаемое значение> 0, то просмотрите набор записи и используйте FD_ISSET, чтобы выяснить, какие из них все еще установлены. Это те, которые доступны для записи.

Ваш код совсем не соответствует этому шаблону. Кроме того, важная задача настройки основного набора не отображается.

0 голосов
/ 21 мая 2011

Я не верю, что вам разрешено копировать-создавать объекты fd_set. Единственный гарантированный способ - полностью перестроить набор, используя FD_SET перед каждым вызовом select. Кроме того, вы пишете в список сокетов, которые вы хотите выбрать, прежде чем вызывать select. Это не имеет смысла.

Можете ли вы использовать poll вместо этого? Это намного более дружелюбный API.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...