如何在QT中接收适当的UDP数据包

How to receive proper UDP packet in QT?

本文关键字:UDP 数据包 QT      更新时间:2023-10-16

我正在尝试编写一个QT程序以接收UDP数据包。我正在尝试从数据包发送器软件接收这是我的代码

    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; 
 };

读取的信号和相应的插槽不起作用。我可以在Wireshark中看到数据包。如果我尝试在循环中连续接收数据包,我可以看到数据报。这可能是信号和插槽不正常的原因。待办事项操作运行良好。

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

.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

mainwindow.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;
    }
}

mainwindow.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

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

在我的情况下,这无效,因为总会有"假人"数据报留在内存中的某个地方,即使haspendingDatagrams()返回false,我也必须再一次调用readdatagram,以便让我的程序接收较新的数据报。我的答案无论如何在这里https://stackoverflow.com/a/74056997/11414500祝你好运!

@gabriel答案对我不起作用,因为它使用了旧的connect语法。我将其更新为以下(QT 6):

// udpclient.h
#ifndef UDPCLIENT_H
#define UDPCLIENT_H
#include <QObject>
#include <QUdpSocket>
class UdpClient: public QObject
{
    Q_OBJECT
public:
    explicit UdpClient(QObject *parent);
    void initSocket();
private:
    void processPendingDatagrams();
    QUdpSocket *socket=nullptr;
};
#endif // UDPCLIENT_H
// udpclient.cpp
#include "udpclient.h"
UdpClient::UdpClient(QObject *parent) : QObject(parent) {
}
void UdpClient::initSocket()
{
    socket = new QUdpSocket(this);
    bool result =  socket->bind(QHostAddress::AnyIPv4, 4999);
    if(result)
    {
        qDebug() << "Socket PASS";
    }
    else
    {
        qDebug() << "Socket FAIL";
    }
    processPendingDatagrams();
    connect(socket, &QUdpSocket::readyRead, this, &UdpClient::processPendingDatagrams);
}
void UdpClient::processPendingDatagrams()
{
    qDebug() << "in !";
    QHostAddress sender;
    quint16 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;
    }
}

它可以在函数或main()中使用为:

auto udpClient = new UdpClient(0);
udpClient->initSocket();