1 UDP简介

UDP(User Datagram Protocol,即用户数据报协议)是一个轻量级的,不可靠的,面向数据报的无连接协议。由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。

UDP通信示意图如下:

UDP消息传送有三种模式,分别是单播、广播和组播三种模式。

①单播(unicast):单播用于两个主机之间的端对端通信,需要知道对方的IP地址与端口。

②广播(broadcast):广播UDP与单播UDP的区别就是IP地址不同,广播一般使用广播地址255.255.255.255,将消息发送到在同一广播(也就是局域网内同一网段)网络上的每个主机。

③组播(multicast):组播(多点广播),也称为多播,将网络中同一业务类型主机进行了逻辑上的分组,进行数据收发的时候其数据仅仅在同一分组中进行,其他的主机没有加入此分组不能收发对应的数据。

在广域网上广播的时候,其中的交换机和路由器只向需要获取数据的主机复制并转发数据。主机可以向路由器请求加入或退出某个组,网络中的路由器和交换机有选择地复制并传输数据,将数据仅仅传输给组内的主机。多播的这种功能,可以一次将数据发送到多个主机,又能保证不影响其他不需要(未加入组)的主机的其他通信。

注意:单播一样和多播是允许在广域网即Internet上进行传输的,而广播仅仅在同一局域网上才能进行。

2 与TCP对比

(1)通信方式

  • TCP:Qt中使用QTcpServer和QTcpSocket两个类来实现基于TCP的通信。QTcpServer用于创建服务器端应用程序,而QTcpSocket既可以用于创建客户端。TCP是面向连接的,所以在使用QTcpSocket时,需要先调用connectToHost方法来建立连接,然后才能发送和接收数据。连接建立后,数据传输是双向的,可以同时进行发送和接收。所以在TCP通信的中我们不仅实现了TCP客户端还实现了TCP服务器。
  • UDP:Qt中使用QUdpSocket一个类来实现基于UDP的通信。UDP是无连接的,使用QUdpSocket时可以直接发送数据,不需要建立连接。发送和接收数据是独立的操作,发送数据使用write方法,接收数据则是通过信号readyRead来处理。所以UDP通信实现起来更加容易,UDP不分客户端和服务器,只需要创建一个工程即可。

(2)数据流与数据报

  • TCP:QTcpSocket处理的是面向流的数据,数据在发送和接收时是以连续的字节流形式进行的,没有明确的数据边界。
  • UDP:QUdpSocket处理的是数据报,每个发送和接收的数据单元都是独立的,具有明确的边界。这使得UDP在处理某些需要独立数据包的应用时更为方便。

(3)可靠性与效率

  • TCP:使用QTcpSocket时,Qt会自动处理数据的可靠性,包括数据的顺序、完整性和重传机制。这使得TCP通信更加稳定,但也意味着会有更多的开销。
  • UDP:使用QUdpSocket时,开发者需要自己处理数据的顺序和完整性。UDP通信效率更高,但可能会有丢包的情况发生。

(4)错误处理

  • TCP:QTcpSocket提供了一些错误信号,如disconnected、error等,可以用来处理连接断开或通信错误的情况。
  • UDP:QUdpSocket同样提供了error信号,但由于UDP的特性,错误处理通常更加简单,主要是处理无法发送或接收数据的情况。

3 设计ui

(1)打开主ui文件,添加一个按钮,功能为UDP测试。并将相应的槽函数设置为跳转到UDP测试页面。

(2)新建socket类,打开ui文件,添加两个按钮,功能分别为打开GPIO7_2引脚和关闭GPIO7_2引脚,添加两个单行输入框(LineEdit)。

4 设置UDP

1
2
3
udpSocket = new QUdpSocket(this);
udpSocket->bind(QHostAddress::Any, 50053);
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));

5 按钮槽函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
* 函数名称:void on_PbSend_released()
* 函数功能:发送UDP数据按钮的槽函数
* 作者:JR.Wang
* 日期:2024.07.28
*/
void socket::on_PbSend_released()
{
QString sendbuf=ui->LineEditSend->text();
QString IP="192.168.10.200";
QString port="6666";
sendMsgToSever(sendbuf,IP,port);
}

/*
* 函数名称:void on_PbClear_released()
* 函数功能:清空接收区按钮的槽函数
* 作者:JR.Wang
* 日期:2024.07.28
*/
void socket::on_PbClear_released()
{
ui->LineEditReceive->clear();
}

6 接收信号槽函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
* 函数名称:void readPendingDatagrams()
* 函数功能:读取UDP数据
* 作者:JR.Wang
* 日期:2024.07.28
*/
void socket::readPendingDatagrams()
{
while (udpSocket->hasPendingDatagrams())
{
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(),datagram.size());
qDebug()<<datagram;
ui->LineEditReceive->setText(datagram);
}
}

7 移植到开发板

运行程序,点击发送按钮,电脑端接收到开发板发来的信息,电脑端发送消息,程序接收区接收到电脑端口消息。

参考文章:

https://blog.csdn.net/qq_53144843/article/details/127153860

https://blog.csdn.net/Yz12333/article/details/138013152