Qt:带有QUdpSocket的SSDP在极少数情况下可以使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt:带有QUdpSocket的SSDP在极少数情况下可以使用相关的知识,希望对你有一定的参考价值。

这个让我疯狂了一段时间。由于我从未做过任何与网络相关的代码,因此我无法总结此实验的结果。

我收到了有关使用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
");
        return;
    }

    ok = socket->joinMulticastGroup(groupAddress);
    if (!ok) {
        printf("Join Multicast Group Failed
");
        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
"        
                       "HOST: 239.255.255.250:1900
" 
                       "MAN: "ssdp:discover"
" 
                       "MX: 5
" 
                       "ST: ***:******-****-***:*******:***********:*
" 
                       "
");

    auto writeOk = socket->writeDatagram(message.data(), groupAddress, port);
    if (writeOk == -1) {
        printf("Writing Datagram failed
");
        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文档提供的完全相同的代码和顺序。
答案

我在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);

以上是关于Qt:带有QUdpSocket的SSDP在极少数情况下可以使用的主要内容,如果未能解决你的问题,请参考以下文章

QT QUdpSocket:没有这样的文件或目录

使用 QUdpSocket 的 Qt4 DNS 服务器

Qt4 DNS 代理 QUdpSocket

如何用Qt的Qudpsocket传输图片文件?

5.关于QT中的网络编程,QTcpSocket,QUdpSocket

QUdpSocket-Qt使用Udp通讯实现服务端和客户端