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% времени это не удается. Когда я пытаюсь напечатать сообщения, ответ, который я получаю, всегда отражает то, что я запрашивал. Независимо от того, как долго я оставлю это, правильный ответ никогда не приходит. С другой стороны, когда условия "просто правильные", обнаружение является безупречным и всегда немедленно возвращает результат.
Ожидаемые результаты: я ожидаю увидеть ответ сервера с дополнительной информацией, такой как местоположение.
Соображения:
- Поскольку мне трудно понять, почему код, связанный с сетью, дает сбой, я не могу сделать вывод из результатов, является ли мой код получателя неправильным или сервер был настроен неправильно. Что может быть индикатором для меня, чтобы использовать? Могут ли на это повлиять такие вещи, как виртуальные частные сети? Имеет ли значение, если сервер работает на моей локальной машине?
- Я прошел через множество итераций, где я пытался использовать различные флаги подключения, уничтожать и сбрасывать объект или сокет, прежде чем пытаться снова, и даже выполнял цикл, который запрашивал более 5000 раз, чтобы понять поведение.
- Если этот код не похож на один, я попытался воспроизвести точно такой же код и порядок, предусмотренный документацией Qt.
0 ответов
Я столкнулся с похожими проблемами на 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);