基于Qt的UDP协议实现及解析数据

版权声明:最终版权归YBAidam所有 https://blog.csdn.net/Aidam_Bo/article/details/85213030

一、前言

UDP 是一个不可靠的,面向数据报的协议。QUdpSocket 类可以用来发送和接收UDP数据报(datagram)。

最常用的使用方式是使用bind()去绑定地址和端口号,然后使用writeDatagram()和readDatagram()去传输数据。

这个socket对象每次往网络中发送报文都会发出bytesWritten()信号。如果你只是想用QUdpSocket发送报文,就不需要调用bind().

当报文到达的时候会发readyRead()信号,在这种情况下,hasPendingDatagrams()会返回true.调用 pendingDatagramSize()方法获取报文的长度。最后调用readDatagram()读取。

二、QUDPSocekt

下面的实例WeatherServery应用程序模拟气象气球的功能,每2秒就发送一个包含当前天气情况的UDP数据报。

#ifndef WEATHERBALLOON_H
#define WEATHERBALLOON_H

#include <QWidget>
#include <QPushButton>
#include <QtNetwork/QUdpSocket>
#include <QTimer>
#include <QDateTime>
namespace Ui {
    class weatherBalloon;
}

class weatherBalloon : public QWidget
{
    Q_OBJECT

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

private slots:
    //处理报文
    void processPendingDatagrams();
    //发送报文
    void sendDatagram();
private:
    Ui::weatherBalloon *ui;
    QUdpSocket udpSocket;
    QTimer timer; 
    double temperature;//温度
    double humidity;//湿度
    double altitude;//高度
};

#endif // WEATHERBALLOON_H

WeatherServer的实现

#include "weatherballoon.h"
#include "ui_weatherballoon.h"

weatherBalloon::weatherBalloon(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::weatherBalloon)
{
    //绑定Socket到指定地址和端口号
    udpSocket.bind(5824);

    ui->setupUi(this);
    connect(ui->btn_close,SIGNAL(clicked()),this,SLOT(close()));
    connect(&timer,SIGNAL(timeout()),this,SLOT(sendDatagram()));
    connect(&udpSocket,SIGNAL(readyRead()),this,SLOT(processPendingDatagrams()));

    timer.start(2*1000);
    temperature = 10.2;
    humidity   = 5.4;
    altitude   = 100.0;
    setWindowTitle(tr("Weather Balloon"));
}

weatherBalloon::~weatherBalloon()
{
    delete ui;
}

//发送报文
void weatherBalloon::sendDatagram(){
    QByteArray datagram;
    QDataStream out(&datagram,QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_8);
    out<<QDateTime::currentDateTime()<<temperature<<humidity<<altitude;
    qDebug()<<QDateTime::currentDateTime();
    QHostAddress address;
    address.setAddress("127.0.0.1");
    udpSocket.writeDatagram(datagram,address,5824);
}

//处理报文
void weatherBalloon::processPendingDatagrams(){
   QByteArray datagram;
   do{
       datagram.resize(udpSocket.pendingDatagramSize());
       udpSocket.readDatagram(datagram.data(),datagram.size());
   }while(udpSocket.hasPendingDatagrams());
   QDateTime dateTime;
   double temperature;
   double humidity;
   double altitude;
   qDebug()<<"recive date ";
   QDataStream in(&datagram,QIODevice::ReadOnly);
   in.setVersion(QDataStream::Qt_4_8);
   in>>dateTime>>temperature>>humidity>>altitude;


   ui->lineEdit_Date->setText(dateTime.date().toString());
   ui->lineEdit_CurrentTime->setText(dateTime.time().toString());
   ui->lineEdit_Temperature->setText(tr("%1 °c").arg(temperature));
   ui->lineEdit_Humidity->setText(tr("%1%").arg(humidity));
   ui->lineEdit_Alt->setText(tr("%1 m").arg(altitude));

}

三、发送结构体及解析其数据

发送端:
头文件中建立结构体state:

#pragma pack(1) //此时编译器字节对齐方式为1byte,且为不进栈模式[#pragma push(pack,1)]
struct state{
    int order;
    int speed;
    double longitude;
    double latitude;
};

#pragma pack()



实现cpp文件:

state data;
data.order=1;
data.speed=50;
data.longitude=120.34;
data.latitude=36.89;
udpSocket->writeDatagram((char*)&data,sizeof(data),QQHostAddress::Broadcast,port);



接收端
在头文件中建立结构体,与发送端一样。

接收cpp文件:

state datagram;
udpSocket->readDatagram((char*)&datagram,sizeof(datagram));



然后就可以读取结构体数据,像这样:

int Order=datagram.order;
int Speed=datagram.speed;
double Longitude=datagram.longitude;
double Latitude=datagram.latitude;


 


参考资料:

C++ GUI Qt5 编程

Qt 帮助文档中关于QUdpSocket

猜你喜欢

转载自blog.csdn.net/Aidam_Bo/article/details/85213030