首页 > 解决方案 > Qt:带有 QUdpSocket 的 SSDP 在极少数情况下工作

问题描述

这个已经让我发疯了一段时间。由于我从未做过任何网络相关的代码,我无法得出这个实验的结果。

我收到了有关使用 SSDP 广播相关信息的服务器的信息。根据标准,我获得了 IP 和端口。我还获得了需要在接收方使用的查询和搜索目标。我在这个例子中使用了我最新的迭代,在这个例子中我决定使用一个管理发现的单例类。我使用的真正的 ST 字符串也是我提供的,忽略下面的...

发现管理器.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;
};

发现管理器.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 文档提供的完全相同的代码和顺序。

标签: c++qtnetworkingudpssdp

解决方案


我在 Mac 上遇到了类似的问题,但在 iOS 上遇到了不同的代码。你设法解决了吗?如何?

好吧,我必须得到响应的唯一方法是绑定到与 1900 不同的端口,但我不知道是否是正确的方法。我通过使用wireshark 发现了这一点,例如Google Chrome 在发送M-SEARCH 和1900 作为目标时使用“随机”端口作为源端口。

通过将绑定端口设置为 1900,我只能将数据报发送到“239.255.255.250”,例如其他软件 M-SEARCH 或设备通知消息。

这可以使您的代码正常工作:

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

推荐阅读