QUdpSocket 类理论总结
- 一、概述
- 二、使用流程
- 三、QNetworkDatagram 简述
一、概述
UDP (User Datagram Protocol)是一种轻量级的、不可靠的、面向数据报的、无连接的协议。当可靠性不重要时,可以使用它。QUdpSocket是QAbstractSocket的子类,允许发送和接收UDP数据报。
经典的UDP编程流程
二、使用流程
使用这个类最常见的方式是使用 bind() 绑定一个地址和端口,然后调用 writeDatagram() 和 readDatagram() / receiveDatagram() 来传输数据。如果想使用标准的QIODevice函数read()、readLine()、write()等,必须首先通过调用connectToHost()将套接字直接连接到另一端。
每当向网络写入数据报时,套接字就发出 bytesWritten() 信号。如果你只是想发送数据报,不需要调用bind()。
每当数据报到达时,就会触发readyRead()信号。在这种情况下,haspendingdatagram()返回true。调用pendingDatagramSize()获取待处理的第一个数据报的大小,再调用readDatagram()或receiveDatagram()读取它。
注意:当收到readyRead()信号时,应该读取传入的数据报,否则将不会为下一个数据报发出此信号。
void Server::initSocket()
{
udpSocket = new QUdpSocket(this);
udpSocket->bind(QHostAddress::LocalHost, 7755);
connect(udpSocket, &QUdpSocket::readyRead,
this, &Server::readPendingDatagrams);
}
void Server::readPendingDatagrams()
{
while (udpSocket->hasPendingDatagrams()) {
QNetworkDatagram datagram = udpSocket->receiveDatagram();
processTheDatagram(datagram);
}
}
QUdpSocket也支持UDP组播。使用 joinMulticastGroup() 和 leaveMulticastGroup() 来控制组成员关系,并使用 QAbstractSocket::MulticastTtlOption 和 QAbstractSocket::MulticastLoopbackOption 来设置TTL和环回套接字选项。使用 setMulticastInterface() 来控制组播数据报的出接口,使用 multicastInterface() 来查询出接口。
使用 QUdpSocket,您还可以使用 connectToHost() 建立到UDP服务器的虚拟连接,然后使用 read() 和 write() 交换数据报,而无需指定每个数据报的接收方。
三、QNetworkDatagram 简述
QNetworkDatagram可与QUdpSocket类一起使用,表示UDP (User Datagram Protocol,用户数据报协议)数据报中包含的完整信息。QNetworkDatagram封装了一个数据报的下列信息:
- 有效载荷数据;
- 发件人地址及端口号;
- 目的地址和端口号;
- 剩余跳数限制(在IPv4上,该字段通常称为time to live - TTL);
- 接收或发送数据报的网络接口索引。
QUdpSocket将尝试在所有操作系统上尽可能匹配通用行为,但在某些操作系统中并不能获得上述所有元数据。使用 QUdpSocket::writeDatagram() 发送时不能在数据报上设置的元数据将被静默丢弃。
接收到数据后,senderAddress() 和 senderPort() 属性中包含发送数据报的那一端的地址和端口,而 destinationAddress() 和 destinationPort() 属性中包含数据报中的目标地址。这通常是当前机器的本地地址,但也可以是IPv4广播地址(例如“255.255.255.255”)或IPv4或IPv6组播地址。应用程序可能会发现,确定数据报是通过单播寻址专门发送到本机的,还是发送到多个目的地的,是很有用的。
发送时,senderAddress() 和 senderPort() 应该包含发送时使用的本地地址。发送地址必须是分配给这台机器的地址,可以通过 QNetworkInterface 获得,端口号必须是套接字绑定的端口号。任何一个字段都可以不设置,由操作系统用默认值填充。destinationAddress() 和 destinationPort() 字段可以设置为与UDP套接字当前关联的目标地址不同的目标地址。
通常,在发送数据报以响应之前收到的数据报时,会将 destinationAddress() 设置为传入数据报的 senderAddress() ,端口号也是类似的。为了简化这一常见过程,QNetworkDatagram提供了 makeReply() 函数。
对于接收到的数据报,hopCount()函数包含了该数据包剩余的跳数限制。发送时,包含要设置的跳数限制。大多数协议将这个值设置为默认值,并由操作系统决定使用的最佳值。IPv4上的多播通常使用这个字段来表示多播组的范围(link-local, local to a organization or global)。
interfaceIndex()函数包含了操作系统接收到数据包的接口的索引。这个值与可以在QHostAddress::scopeId()属性上设置的值相同,并且与QNetworkInterface::index()属性匹配。在向全局地址发送报文时,不需要设置接口索引,操作系统会根据系统路由表选择正确的接口索引。在将数据报发送到链路本地目的地(无论是单播还是多播)时,这个属性很重要。
功能的支持
并非所有操作系统都支持QNetworkDatagram的某些特性。所有系统只支持远程主机的地址和端口(接收数据包的发送端和发送数据包的目的地)。在大多数操作系统上,其他特性仅支持IPv6。软件应该在运行时检查是否可以确定IPv4地址的其余部分。