【问题标题】:Qt skipping UDP packet after a predictable number of secondsQt 在可预测的秒数后跳过 UDP 数据包
【发布时间】:2017-07-20 15:59:17
【问题描述】:

我有这个程序,它通过与通过电缆直接连接到我的计算机网络适配器的设备进行通信,随着时间的推移进行测量。通信使用 UDP。

这里的问题是,在 N 秒后程序未能拾取它所期望的数据包(请求数据包被发送到设备,然后它等待回复)。我有一个变量决定每次测量之间要等待多长时间,通过改变它我不会改变 N,所以发送的数据包数量是不相关的。如果我重新启动应用程序并运行一个新序列(如在一长串测量之间有延迟),它会在 N 秒后再次停止。

N 的观测值:~200s,~320s。 (有时会发生变化(可能在重新启动时))

我使用wireshark捕获数据包,据此数据包实际上是由网络适配器接收的,因此这里发生故障的不是设备。我的应用程序使用 Qt 并且是用 C++ 编写的。

我有自己的 UDP 类,它使用 QUdpSocket,它扩展 QAbstractSocket,而 QIODevice 又扩展了 QIODevice,我看到在 QIODevice 类中声明了 readyRead 信号,这是我期望但无法接收的信号。

所以出了什么问题?为什么 Qt 没有反应?为什么在一定的时间之后呢? 如果需要更具体的细节/代码,请告诉我。

我的 udp 类的构造函数的一部分

socket = new QUdpSocket();
socket->connectToHost(QHostAddress(*ipaddr), COM_LUX_PORT);    
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));

我的 udp 类中的 readyRead 插槽

void Udp::readyRead(){
    // when data comes in
    QByteArray buffer;
    buffer.resize(socket->pendingDatagramSize());

    QHostAddress sender;
    quint16 senderPort;

    socket->readDatagram(buffer.data(), buffer.size(),
                         &sender, &senderPort);

    qDebug() << "1Message: " << buffer.toHex();
    emit messageReceived(buffer);
}

标头中的信号和槽

signals:
    /*!
      Signal for transferring the received messages
    */
    void messageReceived(QByteArray buffer);
public slots:
    void readyRead();
    void readyReadSock2();
    void reConnectToIp(QString addr);

private slots:
    void slotTimeout();

EDIT#1:我发现this 类似的问题,但有一个主要区别,因为我收到数据包,直到某一点。

EDIT#2:一些相关代码。

【问题讨论】:

  • 是的,需要代码。有运行多年的 UDP 软件,你观察到的应该不会发生。
  • 在那里,我添加了一些代码,但是当问题出现时,我遇到的“阻塞”发生在代码中的这一点之前。
  • 只是一个想法。您是否尝试使用 bind() 而不是 connectToHost()?此外,您可能需要检查 error() 信号。
  • 会的,谢谢!我会在收集到更多信息后立即更新,不过由于问题的延迟性质,可能需要几分钟时间。
  • @Jontahan 是的,这就是问题的根源。不,我认为您应该完全移除阻塞并异步使用 API

标签: c++ qt sockets udp


【解决方案1】:

Ilbeldus 提供了解决方案。

我经常阻塞线程的事实似乎是原因。我仍然不明白为什么它只在几分钟后失败,以及为什么每次都在相同的时间后失败(所以欢迎解释)。然而问题解决了。谢谢大家的帮助!

【讨论】:

  • 我会在 2 天内将此答案标记为已接受(这是一个冷却时间),因为每个人都在问题评论部分回答。以便有类似问题的人可以将此线程用作资源。
  • 我相信,为了更好地理解,您必须考虑事件循环(以及它在您的应用程序中的核心作用)。如果在事件上调用了信号处理程序,并且它消耗了太多时间,则事件循环在这段时间内被阻塞。可能还有其他需要定期完成的事情(简单示例:周期性计时器)。所有这些事情(如果在同一个线程中)都是由停滞的事件循环触发的,因此必须等待。这个解释有点模糊和不具体。使用MCVE,它可能更具体。
  • 用调试器很容易证明这一点:在感兴趣的信号处理程序中设置一个断点,一旦它“触发”,查看调用堆栈。对我来说,这往往是非常有启发性的......
猜你喜欢
  • 2021-01-21
  • 1970-01-01
  • 2023-02-08
  • 1970-01-01
  • 2015-02-08
  • 2012-03-19
  • 2017-07-19
  • 2022-07-08
  • 2017-07-31
相关资源
最近更新 更多