Link-локальная Многоадресная рассылка по QUdpSocket в Windows


Я пытаюсь отправить UDP-телеграмму с помощью link-local multicast. Я использую Qt, который предлагает QUdpSocket. Я смог сделать это на Linux, но не могу получить код, работающий на Windows.

Мой первый код выглядел так:

udp.writeDatagram(QByteArray("hello world"), QHostAddress("FF02::1"), 4321);

Он работает на Linux, но не на Windows. Я даже попытался запустить приложение с правами администратора. writeDatagram() возвращает размер телеграммы в обеих системах.

Единственный совет, который я нашел, - это отправить телеграмму по определенной сети. взаимодействие. Мой код для этого подхода:
foreach(const QHostAddress& address, QNetworkInterface::allAddresses()) {
    udp.bind(address, 0);

    if(address.protocol() == QAbstractSocket::IPv6Protocol) {
        udp.writeDatagram(data, QHostAddress("FF02::1"), 4321);
    }

    udp.close();
}

Код снова посылает телеграмму на Linux, но не на Windows. allAddresses() возвращает IPv6 link-локальные адреса в обеих операционных системах.

QUdpSocket::joinMulticastGroup() ничего не сделал также (как и ожидалось, потому что это касается только получения).

Я использую Wireshark (на отправляющей машине и другой машине в сети), чтобы проверить, отправляются ли телеграммы. Чтобы проверить, работает ли сетевой код вообще, я добавил трансляцию IPv4, которая работает на Windows с обоими решениями. Я знаю, что моя Windows поддерживает IPv6, потому что у нее есть локальный адрес связи. Брандмауэр Windows был отключен во время тестов, и у меня нет другого брандмауэра, установленного в тестовой системе. Полный тестовый код можно найти здесь в Gist.

Почему Windows отказывается отправлять телеграмму? В моем коде чего-то не хватает или в Qt есть ошибка? У кого-нибудь это получилось? Пожалуйста помочь.

1 2

1 ответ:

Второй подход был правильным. Я должен был open() сокеты снова после close()ing их. Я думаю, что это было сделано в bind(), потому что сокет был открыт после создания объекта ...

Рабочий код:

foreach(const QHostAddress& address, QNetworkInterface::allAddresses()) {
    if(address.protocol() == QAbstractSocket::IPv6Protocol) {
        _udp.bind(address, 0);
        _udp.writeDatagram(data, QHostAddress("FF02::1"), DISCO_PORT);

        _udp.close();
        _udp.open(QUdpSocket::ReadWrite);
    }

}