UDP(User Datagram Protocol,用户数据报协议)是一个轻量级的、不可靠的、面向数据报的、无连接的协议,用于可靠性不是非常重要的情况下,例如,一个服务器报告一天的时间可以选择UDP。如果一个包含时间的数据报丢失了,那么客户端可以简单地发送另外一个请求。UDP一般分为发送端和接收端,其示意图如下:
QUdpSocket类用来发送和接收UDP数据报,继承自QAbstractSocket。这里的Socket就是所谓的“套接字”,简单来说,套接字就是一个IP地址加一个port端口号。其中IP地址指定了网络中的一台主机,而端口号指定了该主机上的一个网络程序,这样使用套接字就可以实现网络上两台主机上的两个应用程序之间的通信。
QUdpSocket支持IPv4广播。广播一般用来实现网络发现协议,例如,查找网络上哪个主机拥有最多的硬盘空间,一个主机向网络中广播一个数据报,然后所有其他的主机都接收这个数据报,每一个主机接收到一个请求,然后发送应答给发送端,告知其当前的可用磁盘空间。发送端一直等待,直到它接收到所有主机的答复,然后可以选择拥有最多空闲空间的服务器来存储数据。要广播一个数据报,只需要发送它到一个特殊的地址QHostAddress::Broadcast(即255.255.255.255),或者是本地网络的广播地址。
先编写发送端程序:
新建Qt Widgets应用,项目名称为udpsender,基类选择QDialog,类名为Sender,完成后向udpsender.pro文件中添加“QT += network”一行代码。
其sender.h文件如下:
#ifndef SENDER_H
#define SENDER_H
#include <QDialog>
namespace Ui {
class Sender;
}
class QUdpSocket; //类的前置声明
class Sender : public QDialog
{
Q_OBJECT
public:
explicit Sender(QWidget *parent = 0);
~Sender();
private slots:
void on_pushButton_clicked();
private:
QUdpSocket *sender;
private:
Ui::Sender *ui;
};
#endif // SENDER_H
sender.cpp代码如下:
#include "sender.h"
#include "ui_sender.h"
#include <QtNetwork>
Sender::Sender(QWidget *parent) :
QDialog(parent),
ui(new Ui::Sender)
{
ui->setupUi(this);
sender=new QUdpSocket(this);
}
Sender::~Sender()
{
delete ui;
}
void Sender::on_pushButton_clicked()
{
QByteArray datagram = "hello world!";
//发送数据报
sender->writeDatagram(datagram.data(), datagram.size(), QHostAddress::Broadcast, 45454);
}
现在可以运行一下程序。下面再来添加接收端程序。
同样新建项目跟发送端一样也是新建Qt Widgets应用,项目名称为udpreceiver,基类选择QDialog,类名为Receiver,完成后向udpreceiver.pro文件中添加“QT += network”一行代码。
receiver.h代码如下:
#ifndef RECEIVER_H
#define RECEIVER_H
#include <QDialog>
namespace Ui {
class Receiver;
}
class QUdpSocket; //类的前置说明
class Receiver : public QDialog
{
Q_OBJECT
public:
explicit Receiver(QWidget *parent = 0);
~Receiver();
private:
QUdpSocket *receiver;
private slots:
void processPendingDatagram();
private:
Ui::Receiver *ui;
};
#endif // RECEIVER_H
receiver.cpp代码如下:
#include "receiver.h"
#include "ui_receiver.h"
#include <QtNetwork>
Receiver::Receiver(QWidget *parent) :
QDialog(parent),
ui(new Ui::Receiver)
{
ui->setupUi(this);
receiver=new QUdpSocket(this);
receiver->bind(45454, QUdpSocket::ShareAddress); //绑定IP地址和端口号
connect(receiver, &QUdpSocket::readyRead, this, &Receiver::processPendingDatagram);
}
Receiver::~Receiver()
{
delete ui;
}
void Receiver::processPendingDatagram()
{
while(receiver->hasPendingDatagrams()) // 拥有等待的数据报
{ QByteArray datagram;
// 设置datagram大小为等待处理的数据报的大小,这样才能接收到完整的数据
datagram.resize(receiver->pendingDatagramSize());
// 接收数据报,将其存放到datagram中
receiver->readDatagram(datagram.data(), datagram.size());
ui->label->setText(datagram); //将获取的数据显示在label中
}
}
同时运行两个程序:单击发送端的“进行广播”按钮,会看到在接收端的label标签中会显示“hello world!”
版权声明:本文为lhw19931201原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。