【问题标题】:How to receive proper UDP packet in QT?如何在 QT 中接收正确的 UDP 数据包?
【发布时间】:2017-07-31 13:56:18
【问题描述】:

我正在尝试编写一个 QT 程序来接收 UDP 数据包。我正在尝试从 Packet Sender 软件接收 这是我的代码

    socket = new QUdpSocket(this);
    bool result =  socket->bind(QHostAddress("150.100.50.88"),45454);
    qDebug() << result;
    if(result)
    {
        qDebug << "PASS";
    }
    else
    {
        qDebug << "FAIL";
    }
    processPendingDatagrams();
    connect(socket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()),Qt::QueuedConnection);


    void UDP::processPendingDatagrams() 
    {
        QHostAddress sender;
        u_int16_t port;
        while (socket->hasPendingDatagrams())
        {
            QByteArray datagram;
            datagram.resize(socket->pendingDatagramSize());
            socket->readDatagram(datagram.data(),datagram.size(),&sender,&port);
           qDebug() <<"Message From :: " << sender.toString();
           qDebug() <<"Port From :: "<< port;
           qDebug() <<"Message :: " << datagram;    
       } //! [2] 
   }

UDP.h:

 class UDP : public QObject 
 {
 Q_OBJECT public:
 explicit UDP(QObject *parent = 0);

 signals:

 public slots:
 void SendDatagram(u_int8_t,u_int8_t,u_int8_t);

 private slots:
 void processPendingDatagrams();

 private :
 QUdpSocket *socket; 
 };

readReady 信号和相应的插槽不工作。我可以在 Wireshark 中看到数据包。 如果我尝试在循环中连续接收数据包,我可以看到数据报。信号和插槽无法正常工作的原因可能是什么。发送操作运行良好。

【问题讨论】:

  • 是插槽中.h 中的 void UDP::processPendingDatagrams() 定义,而不仅仅是函数? (带有公共/受保护/私有插槽:)
  • void UDP::processPendingDatagrams() 被声明为公共函数而不是插槽。我已将类添加到我的问题中
  • 如果你想像在connect中一样把它当作一个槽使用,你应该把它移到槽中。如果它是一个函数,它将不会被调用,因为 Qt 无法将它与信号链接。
  • 我已将声明移至 Slots,即使在此之后没有任何变化。在 wireshark 中,我得到 Destination Unreachable (port unreachable)。
  • 如果 oyu 在这里接收数据包,您应该将 ip 更改为 QHostAddress::AnyIPv4。并尝试另一个端口。 (如果你在linux上,你可以尝试用nc通过netcat发送udp数据包)

标签: c++ qt sockets udp


【解决方案1】:

我正在尝试编写一个 Qt 应用程序,它使用 Gstreamer 管道播放从 udp 套接字接收的 .mp4 文件。 有同样的问题。

main.cpp

int main(int argc, char *argv[])`enter code here`
{
    QApplication a(argc, argv);

    QWidget *window = new QWidget;
    QVideoWidget *videoWidget = new QVideoWidget;
    QBoxLayout *layout = new QVBoxLayout;
    QMediaPlayer *player = new QMediaPlayer;
    QProcess *process = new QProcess;

    layout->addWidget(videoWidget);
    window->setLayout(layout);
    window->show();
    player->setVideoOutput(videoWidget);

    QString program = "gst-launch-1.0";
    QStringList arguments;
     arguments << "udpsrc" << "port=34400" << "caps=application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)JPEG, payload=(int)26" << "!" << "rtpjpegdepay" << "!" << "jpegdec" << "!" << "filesink location=a.mp4";
process->setReadChannel(QProcess::StandardError);
    process->start(program, arguments);

    while (!process->waitForReadyRead()) {}

    player->setMedia(QMediaContent(), process);
    player->play();

    return a.exec();
}
```

【讨论】:

  • 您应该只回复答案。如果此帖子的答案对您没有帮助,请创建一个新问题/帖子并参考此问题。
【解决方案2】:

此代码对我有用。请尝试一下。

.pro:

#-------------------------------------------------
#
# Project created by QtCreator 2017-03-10T11:44:19
#
#-------------------------------------------------

QT       += core gui network

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = test
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

主窗口.cpp:

#include "mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    socket = new QUdpSocket(this);
        bool result =  socket->bind(QHostAddress::AnyIPv4, 45454);
        qDebug() << result;
        if(result)
        {
            qDebug() << "PASS";
        }
        else
        {
            qDebug() << "FAIL";
        }
        processPendingDatagrams();
        connect(socket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams()),Qt::QueuedConnection);
}

MainWindow::~MainWindow()
{
}

void MainWindow::processPendingDatagrams()
 {
    qDebug() << "in !";
    QHostAddress sender;
    u_int16_t port;
    while (socket->hasPendingDatagrams())
    {
         QByteArray datagram;
         datagram.resize(socket->pendingDatagramSize());
         socket->readDatagram(datagram.data(),datagram.size(),&sender,&port);
        qDebug() <<"Message From :: " << sender.toString();
        qDebug() <<"Port From :: "<< port;
        qDebug() <<"Message :: " << datagram;
    }
}

主窗口.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QUdpSocket>


class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void processPendingDatagrams();
private:
    QUdpSocket *socket = nullptr;
};

#endif // MAINWINDOW_H

main.cpp:

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

尝试使用 netcat 的命令:

 netcat -u 127.0.0.1 45454

运行命令后,只需键入任何内容并按回车键。

【讨论】:

  • 我想知道你的开发环境是什么。我在 Ubuntu Qt5.9.5 上有类似的设置,但是在触发 processPendingDatagrams() 插槽时遇到问题。 stackoverflow.com/questions/54209604/…
  • 我在 Ubuntu 和 Windows 10 上都试过了。没有 QCoreApplication 和 app.exec() 信号和插槽无法在 Qt 中工作。确实 Qt 的信号槽被放入一个队列中,需要在 app.exec 期间读取。在您的其他问题中,您不要让 Qt 那样做。
猜你喜欢
  • 2019-05-31
  • 2011-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多