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.

Эхо, вероятно, связано с тем, что вы привязаны к прослушиванию на порту 1900, поэтому, когда вы отправляете широковещательную рассылку всем на порт 1900, маршрутизатор отправляет его прямо вам, и вы его получаете. Возможно, это также мешает реальным ответам других устройств в сети?

Wilco 27.03.2020 10:14
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
524
1

Ответы 1

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

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

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

Это должно заставить ваш код работать:

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

Другие вопросы по теме