Выбор сокета UDP () возвращает 1 без задержки (тайм-аут) при некоторых условиях - PullRequest
0 голосов
/ 30 июня 2018

Я столкнулся с проблемой при разработке клиентского приложения.

Я хочу использовать неблокирующие сокеты UDP в моем приложении для связи с сервером. Я использую библиотеку winsock2 в Windows.

Но ... Почему-то у меня странное поведение функции select() при некоторых условиях:

  1. Сокет не имеет привязанного адреса и порта (это сокет на стороне клиента, поэтому он не нужен).
  2. До select() Я отправляю данные на мой локальный адрес и на какой-то порт с вызовом sendto.
    • Например: 192.168.1.2

При этих условиях select() мгновенно ( даже без ожидания тайм-аута ) возвращает 1. Как будто у меня есть готовый пакет. Но если позвонить recvFrom, то он обязательно вернет -1.


  1. Если я отправляю свои пакеты от клиента на любой другой адрес (который не является моим адресом в локальной сети), тогда select() работает как задумано.
  2. Также select() работает так, как задумано, если не отправляет пакеты на какой-либо адрес перед вызовом select().

Метод инициализации сокета:

bool CUdpSocket::initialize()
{
  _handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

  ... error processing code, returns false if error...
}

Метод, который использует select(). Этот метод отлично работает для сокета сервера (с привязанным адресом и портом).

bool CUdpSocket::waitData(s32 timeout_ms)
{
    fd_set readset;
    int result;
    struct timeval tv;

    // Initialize the set.
    FD_ZERO(&readset);
    FD_SET(_handle, &readset);

    // Initialize time out struct.
    tv.tv_sec = 0;
    tv.tv_usec = timeout_ms * 1000;

    result = select(_handle + 1, &readset, NULL, NULL, &tv);

    // Timeout with no data.
    if (result == 0) {
        return false; // Get out of here!
    }

    // Error.
    if (result < 0) {
        // TODO: Maybe throw exception or do something.
        return false;
    } else if (!FD_ISSET(_handle, &readset)) {
        return false; // No data!
    }

    // There is some data!
    return true;
}

1 Ответ

0 голосов
/ 30 июня 2018

Если вы отправляете пакет из несвязанного сокета UDP, ОС выберет для вас используемый порт и свяжет сокет с этим портом - для протокола UDP требуется , чтобы у порта отправки был адрес отправить с.

Так что, если пакет, который вы отправляете, приводит к ответу, тогда имеет смысл возвращать 1 для выбора - это ответ на пакет, который вы отправили.

...