目录
概述
主要接口函数:
UDP通信的实现:
发送点对点消息和广播消息:
UDP组播:
UDP(User Datagram Protocol,用户数据报协议)是轻量的、不可靠的、面向数据报(datagram)、无连接的协议,它可以用于对可靠性要求不高的场合。与TCP通信不同,两个程序之间进行UDP通信无需预先建立持久的socket连接,UDP每次发送数据报都需要指定目标地址和端口。
QUdpSocket类用于实现UDP通信,它从QAbstractSocket类继承,因而与QTcpSocket 共享大部分的接口函数。主要区别是QUdpSocket以数据报传输数据,而不是以连续的数据流。发送数据报使用函数 QUdpSocket:writeDatagram(),数据报的长度一般少于512字节,每个数据报包含发送者和接收者的IP地址和端口等信息。
要进行UDP数据接收,要用QUdpSocket::bind()函数先绑定一个端口,用于接收传入的数据报。当有数据报传入时会发射readyRead()信号,使用readDatagram()函数来读取接收到的数据报。
UDP消息传送有单播、广播、组播三种模式。
单播(unicast)模式:一个UDP客户端发出的数据报只发送到另一个指定地址和端口的UDP客户端,是一对一的数据传输。
广播( broadcast)模式:一个UDP客户端发出的数据报,在同一网络范围内其他所有的UDP客户端都可以收到。QUdpSocket支持IPv4广播。要获取广播数据只需在数据报中指定接收端地址为QHostAddress::Broadcast,一般的广播地址255.255.255.255。
组播(multicast)模式:也称为多播。UDP客户端加入到另一个组播IP地址指定的多播组,成员向组播地址发送的数据报组内成员都可以接收到,类似于QQ群的功能。 QUdpSocket: joinMulticastGroup()函数实现加入多播组的功能,加入多播组后,UDP数据的收发与正常的UDP数据收发方法一样。
QUdpSocket* udpSocket ;
要实现UDP数据的接收,必须先用QUdpSocket:bind()函数绑定一个端口,用于监听传入的数据报,解除绑定则使用abort()函数。代码如下:
//绑定端口
udpSocket->bind(端口号); //返回值为true 或者 false
//解除绑定
udpSocket->abort();
发送点对点消息和广播消息都是用QUdpSocket::writeDatagram()函数。QUdpSocket发送的数据报是QByteArray类型的字节数组。
//str 数据报 argetAddr 目标地址 targetPort 目标端口
udpSocket->writeDatagram(str, targetAddr, targetPort);//发出数据报
//广播消息
udpsocket->writeDatagram(str, QHostAddress::Broadcast, targetPort);
//在广播消息时,只需将目标地址更换为一个特殊地址,即广播地址QHostAddress::Broadcast,一般是255.255.255.255。
读取缓冲区数据报:接收到数据报后发送readyRead()信号。
hasPendingDatagrams()表示是否有待读取的传入数据报。
pendingDatagramSize()返回待读取数据报的字节数。
readDatagram()函数用于读取数据报的内容,其函数原型为:
qint64 QUdpSocket:: readDatagram (char *data, qint64 maxSize, QHostAddress *address = Q_NULLPTR, quint16 *port = Q_NULLPTR)
参数data和 maxSize是必须的,表示最多读取maxSize字节的数据到变量data 里。address和 port变量是可选的,用于获取数据报来源的地址和端口。无需获取来源的地址和端口后面两个参数,可省略。
//读取收到的数括报
while (udpSocket->hasPendingDatagrams())
{
QByteArray datagram;
datagram.resize (udpSocket->pendingDatagramSize());
QHostAddress peerAddr;
quint16 peerPort;
udpSocket->readDatagram (datagram.data(), datagram.size(), &peerAddr, &peerPort);
QString str=datagram.data() ;
}
UDP组播是主机之间的“一对一组”的通信模式,当多个客户端加入由一个组播地址定义的多播组之后,客户端向组播地址和端口发送的UDP数据报,组内成员都可以接收到,其功能类似于QQ群。
组播报文的目的地址使用D类IP地址,D类地址不能出现在IP报文的源IP地址字段。用同一个IP多播地址接收多播数据报的所有主机构成了一个组,称为多播组(或组播组)。所有的信息接收者都加入到一个组内,并且一旦加入之后,流向组地址的数据报立即开始向接收者传输,组中的所有成员都能接收到数据报。组中的成员是动态的,主机可以在任何时间加入和离开组。
所以,采用UDP组播必须使用一个组播地址。组播地址是D类IP地址,有特定的地址段。多播组可以是永久的也可以是临时的。多播组地址中,有一部分由官方分配,称为永久多播组。永久多播组保持不变的是它的IP地址,组中的成员构成可以发生变化。永久多播组中成员的数量可以是任意的,甚至可以为零。那些没有保留下来的供永久多播组使用的IP组播地址,可以被临时多播组利用。关于组播IP地址,有如下的一些约定:
224.0.0.0~224.0.0.255:为预留的组播地址(永久组地址),地址224.0.0.0保留不做分配,其他地址供路由协议使用;
224.0.1.0~224.0.1.255:是公用组播地址,可以用于Internet;
224.0.2.0~238.255.255.255:为用户可用的组播地址(临时组地址),全网范围内有效; 239.0.0.0~239.255.255.255:为本地管理组播地址,仅在特定的本地范围内有效。
所以,若是在家庭或办公室局域网内测试UDP组播功能,可以使用的组播地址范围是239.0.0.0~239.255.255.255。
QUdpSocket支持UDP组播,joinMulticastGroup()函数使主机加入一个多播组,leaveMulticastGroup()函数使主机离开一个多播组,UDP组播的特点是使用组播地址,其他的端口绑定、数据报收发等功能的实现与单播UDP完全相同。
QUdpSocket *udpSocket;
QHostAddress groupAddress; //组播地址 记录组播地址
QUdpSocket:.setSocketOption()函数,对socket进行参数设置。
udpSocket->setsocketOption(QAbstractSocket::MulticastTtlOption, 1) ;
将socket的QAbstractSocket::MulticastTtlOption值设置为1。MulticastTtlOption是UDP组播的数据报的生存期,数据报每跨1个路由会减1。缺省值为1,表示多播数据报只能在同一路由下的局域网内传播。
要进行UDP组播通信,UDP客户端必须先加入UDP多播组,也可以随时退出多播组。
加入多播组:
//加入组播 IP IP地址 groupAddress = QHostAddress(IP);//多播组地址 //groupPort 多播组统一的端口 加入组播之前必须先绑定端口号 bind()函数 if (udpSocket->bind(QHostAddress::AnyIPv4, groupPort, QUdpSocket::ShareAddress)) { udpSocket->joinMulticastGroup(groupAddress) ; //加入多播组 } //退出组播 udpSocket->leaveMulticastGroup(groupAddress); udpSocket->abort(); //解除绑定
注意:局域网内的组播地址的范围是239.0.0.0~239.255.255.255,绝对不能使用本机地址作为组播地址。
发送数据报: 使用writeDatagram()函数。目标地址为组播地址
读取数据报:当有新的数据时3发送readyRead信号,触发槽函数读取数据。
//读取数据报 while (udpSocket->hasPendingDatagrams()) //是否有可读的传入数据报 { QByteArray datagram; //pendingDatagramsize() 返回数据的数据报字节数 datagram.resize(udpSocket->pendingDatagramsize()); QHostAddress peerAddr ; quint16 peerPort; //读取数据报内容 udpSocket->readDatagram (datagram.data(), datagram.size(), speerAddr, &peerPort); }