一、描述
UDP(用户数据报协议)是一种轻量级、不可靠、面向数据报的无连接协议。当可靠性不重要时可以使用它。 QUdpSocket 是 QAbstractSocket 的子类,它可以发送和接收 UDP 数据报。
1.1、使用方式
- 使用这个类最常见的方法是使用bind()绑定到一个地址和端口,然后调用writeDatagram()和readDatagram()/receiveDatagram()来传输数据。
- QAbstractSocket是QIODevice的子类。如果要使用标准 QIODevice 函数 read()、readLine()、write() 等读写数据,必须首先通过调用 connectToHost() 将Socket直接连接到对等方。
每当数据报到达时就会发出 readyRead() 信号。每次将数据报写入网络时,Socket都会发出 bytesWritten() 信号。如果只想发送数据报不接收数据报,则不需要调用 bind()(不用侦听端口)。
当收到 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);
}
}
1.2、支持多播
QUdpSocket 还支持 UDP 多播。
使用 joinMulticastGroup() 和 leaveMulticastGroup() 加入/离开多播组。
使用 QAbstractSocket::MulticastTtlOption 和 QAbstractSocket::MulticastLoopbackOption 设置 TTL(数据报生存期) 和环回Socket选项。
使用 QUdpSocket,可以使用 connectToHost() 建立到 UDP 服务器的虚拟连接,然后使用 read() 和 write() 交换数据报,而无需为每个数据报指定接收者。
二、成员函数
1、bool hasPendingDatagrams()
如果至少有一个数据报在等待读取,则返回真true。
2、bool joinMulticastGroup(const QHostAddress &groupAddress)
加入由操作系统选择的默认接口上的 groupAddress 指定的多播组,侦听该多播组的信息。Socket必须处于 BoundState 状态,否则会发生错误。
如果尝试加入 IPv4 的多播组组,则Socket不得使用 IPv6 绑定(bind()),必须改用 QHostAddress::AnyIPv4或QHostAddress::Any。
如果成功,此函数返回真; 否则它返回 false 并相应地设置Socket错误。
3、bool joinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface)
重载函数。加入接口iface上的多播组地址groupAddress。
4、bool leaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface)
退出多播组,与上面加入多播组的函数对应。Socket必须处于 BoundState 状态,否则会发生错误。
5、bool leaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface)
退出多播组,重载函数。
6、QNetworkInterface multicastInterface()
返回多播数据报传出接口的网络主机接口信息。 这对应于 IPv4 Socket的 IP_MULTICAST_IF Socket选项和 IPv6 Socket的 IPV6_MULTICAST_IF Socket选项。Socket必须在 BoundState 中,否则返回无效的 QNetworkInterface。
7、qint64 pendingDatagramSize()
返回第一个挂起的 UDP 数据报(等待读取的数据报)的大小。如果没有可用的数据报,则返回 -1。
8、qint64 readDatagram(char *data, qint64 maxSize, QHostAddress *address = nullptr, quint16 *port = nullptr)
接收不大于 maxSize 字节的数据报并将其存储在 data 中。 发送方的主机地址和端口存储在 *address 和 *port 中。
成功返回数据报的大小; 否则返回-1。
如果 maxSize 太小,数据报的其余部分将丢失。 为避免数据丢失,请在尝试读取之前调用 pendingDatagramSize() 以确定待定数据报的大小。 如果 maxSize 为 0,则数据报将被丢弃。
9、QNetworkDatagram receiveDatagram(qint64 maxSize = -1)
接收一个不大于 maxSize 字节的数据报,并在 QNetworkDatagram 对象中返回它。如果可能,该函数还将尝试在接收时确定数据报的目标地址、端口和路由跳数。
如果 maxSize 太小,数据报的其余部分将丢失。 如果 maxSize 为 0,则数据报将被丢弃。 如果 maxSize 为 -1(默认值),该函数将尝试读取整个数据报。
10、void setMulticastInterface(const QNetworkInterface &iface)
将多播数据报传出接口设置为接口 iface。这对应于 IPv4 Socket的 IP_MULTICAST_IF 选项和 IPv6 Socket的 IPV6_MULTICAST_IF 选项。 Socket必须为 BoundState 状态中。
11、qint64 writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port)
将数据大小为 size 的数据报发送到相应的地址和端口。 返回成功发送的字节数; 否则返回-1。
数据报的最大大小依赖于平台。如果数据报太大,此函数将返回 -1,而 error() 将返回 DatagramTooLargeError。
通常不建议发送大于 512 字节的数据报,因为即使它们成功发送,它们也可能在到达最终目的地之前被 IP 层分段。
警告:在连接的 UDP Socket上调用此函数可能会导致错误并且没有数据包被发送。 如果您使用连接的Socket,请使用 write() 发送数据报。
12、qint64 writeDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port)
重载函数。
相关博文: