Qt: SSDP с QUdpSocket работает в редких случаях

Это сводит меня с ума какое-то время. Поскольку я никогда не занимался программным обеспечением, связанным с сетью, я не могу подвести итоги этого эксперимента.

Мне предоставлена ​​информация о сервере, который транслирует соответствующую информацию с использованием SSDP. Мне дали IP и порт в соответствии со стандартом. Мне также дали запрос и цель поиска, которые мне нужно использовать на стороне получателя. Я использую свою последнюю итерацию для этого примера, в котором я решил использовать одноэлементный класс, который управляет обнаружением. Настоящая строка ST, которую я использую, - это та, которую я также предоставил, не обращайте внимания на приведенную ниже...

DiscoveryManager.h

class DiscoveryManager : public QObject
{

private:
    DiscoveryManager( QObject *parent=0 );
public:
    ~DiscoveryManager();

    // Public Accessor for the singleton instance of the class
    static DiscoveryManager* Instance();

    void Discover();

public:
    void readPending();

private:
    // Singleton instance of the class
    static DiscoveryManager* _instance;
    QUdpSocket* socket;
};

DiscoveryManager.cpp

// Definition of singleton instance
DiscoveryManager* DiscoveryManager::_instance;

// Network Parameters
quint16 port = 1900;
QHostAddress groupAddress = QHostAddress("239.255.255.250");

DiscoveryManager::DiscoveryManager(QObject *parent)
    : QObject(parent)   
    , socket( nullptr )
{
    socket = new QUdpSocket(this);
    auto ok = m_sock->bind(QHostAddress::AnyIPv4, port, QUdpSocket::ShareAddress);
    if (!ok) 
    {
        printf("Bind Error\n");
        return;
    }

    ok = socket->joinMulticastGroup(groupAddress);
    if (!ok) {
        printf("Join Multicast Group Failed\n");
        return;
    }

    connect(socket, SIGNAL(readyRead()), this, SLOT(readPending()));
}

DiscoveryManager* DiscoveryManager::Instance()
{
  if(_instance == nullptr)
  {
    _instance = new DiscoveryManager();
  }
  return _instance;
}

void
DiscoveryManager::startDiscovery()
{
    QByteArray message("M-SEARCH * HTTP/1.1\r\n"        \
                       "HOST: 239.255.255.250:1900\r\n" \
                       "MAN: \"ssdp:discover\"\r\n" \
                       "MX: 5\r\n" \
                       "ST: ***:******-****-***:*******:***********:*\r\n" \
                       "\r\n");

    auto writeOk = socket->writeDatagram(message.data(), groupAddress, port);
    if (writeOk == -1) {
        printf("Writing Datagram failed\n");
        return;
    }
}


void
DiscoveryManager::readPending()
{
    while (socket->hasPendingDatagrams()) {
        QByteArray reply;
        reply.resize(socket->pendingDatagramSize());
        socket->readDatagram(reply.data(), reply.size());

        // ... Parse Text Here ...
    }
}

Результаты: в 90 % случаев это не удается. Когда я пытаюсь распечатать сообщения, я получаю ответ, который всегда является эхом того, что я запросил. Независимо от того, как долго я оставляю его, правильный ответ никогда не приходит. С другой стороны, когда условия «в самый раз», обнаружение безупречно и всегда немедленно возвращает результат.

Ожидаемые результаты. Я ожидаю ответа сервера с дополнительной информацией, например о местоположении.

Соображения:

  1. Поскольку мне трудно понять, почему происходит сбой кода, связанного с сетью, я не могу по результатам сделать вывод, является ли мой код получателя неправильным или сервер был настроен неправильно. Что может быть индикатором для меня, чтобы использовать? Могут ли на это повлиять такие вещи, как установленные в пространстве VPN? Имеет ли значение, работает ли сервер на моей локальной машине?
  2. Я прошел через множество итераций, когда пытался использовать разные флаги подключения, уничтожал и сбрасывал объект или сокет, прежде чем пытаться снова, и даже выполнял цикл, который запрашивал более 5000 раз, чтобы понять поведение.
  3. Если этот код не похож на один, я попытался воспроизвести точно такой же код и порядок, указанный в документации Qt.

person AAS.N    schedule 23.05.2018    source источник
comment
Эхо, вероятно, связано с тем, что вы привязаны к прослушиванию через порт 1900, поэтому, когда вы отправляете широковещательную рассылку всем через порт 1900, маршрутизатор отправляет ее прямо вам, и вы ее получаете. Возможно, это также мешает фактическим ответам от других устройств в сети?   -  person Wilco    schedule 27.03.2020


Ответы (1)


Я столкнулся с похожими проблемами на Mac, но с другим кодом на iOS. Вам удалось это исправить? Как?

Ну, единственный способ, которым я должен был получить ответы, - это привязка к порту, отличному от 1900, но я не знаю, правильный ли это способ. Я нашел это с помощью wireshark, например, Google Chrome использует «случайный» порт в качестве исходного порта при отправке M-SEARCH и 1900 в качестве пункта назначения.

Установив порт привязки на 1900, я смог получить только дейтаграммы, отправленные на «239.255.255.250», например, другое программное обеспечение M-SEARCH или сообщения NOTIFY устройств.

Предполагается, что ваш код работает:

auto ok = m_sock->bind(QHostAddress::AnyIPv4, 56123, QUdpSocket::ShareAddress);
person jsseu    schedule 04.02.2019