版权声明:最终版权归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