前言

我们经常使用 “ping” 命令来测试两台主机之间 TCP/IP 通信是否正常, 其实 “ping” 命令的原理就是向对方主机发送 UDP 数据包,然后对方主机确认收到数据包, 如果数据包是否到达的消息及时反馈回来,那么网络就是通的。

准备工作

首先,要使用 Qt 的网络模块需要在 pro 中加上 network(如果是 VS IDE 就在模块选择里勾选上 network):

QT += network

引入相关类的头文件:

#include <QUdpSocket>
#include <QHostAddress>
#include <QNetworkDatagram>

Qt UDP 的操作流程:

QUdpSocket的接口

QUdpSocket 是 QAbstractSocket 的子类,用于发送和接收 UDP 数据报。

可以使用 bind() 显式的绑定地址和端口。参数中的地址可以使用 QHostAddress::Any 绑定任意地址,IPv4 等效于 “0.0.0.0” , IPv6 等效于 “::”;而 BindMode 一般可以设置 ShareAddress(允许其他服务绑定到相同的地址和端口) 和 DontShareAddress(不允许其他服务重新绑定),Windows 上默认等效于 ShareAddress。

bool QAbstractSocket::bind(const QHostAddress &address, quint16 port = 0, QAbstractSocket::BindMode mode = DefaultForPlatform)
bool QAbstractSocket::bind(quint16 port = 0, QAbstractSocket::BindMode mode = DefaultForPlatform)

绑定后,只要 UDP 数据报到达指定的地址和端口,就会触发 readyRead() 信号,此时可在槽函数中读取数据:

void QIODevice::readyRead()

可通过 hasPendingDatagrams() 判断是否有可读数据,通过 pendingDatagramSize() 判断数据长度。

对于数据报的读写依然是使用 read/write 相关接口:

qint64 QUdpSocket::readDatagram(char *data, qint64 maxSize, QHostAddress *address = nullptr, quint16 *port = nullptr)
QNetworkDatagram QUdpSocket::receiveDatagram(qint64 maxSize = -1)
qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port)
qint64 QUdpSocket::writeDatagram(const QNetworkDatagram &datagram)
qint64 QUdpSocket::writeDatagram(const QByteArray &datagram, const QHostAddress &host, quint16 port)

对于单播,可以直接指定目标地址和端口发送:

const QString address_text = "127.0.0.1";
const QHostAddress address = QHostAddress(address_text);
const unsigned short port = 12345;
udpSocket->writeDatagram(QNetworkDatagram(send_data,address,port));

对于广播,需要发送到广播地址 “255.255.255.255”,即使用 QHostAddress::Broadcast:

udpSocket->writeDatagram(QNetworkDatagram(send_data,QHostAddress::Broadcast,port));

对于组播,需要发送到指定的组播地址,不过要对方加入了这个组播(使用 joinMulticastGroup 和 leaveMulticastGroup 加入/退出组播):

//组播ip必须是D类ip
//D类IP段 224.0.0.0 到 239.255.255.255
//且组播地址不能是224.0.0.1
udpSocket->bind(QHostAddress::AnyIPv4,port); //根据Qt示例,组播的话IPv4和v6分开的
udpSocket->joinMulticastGroup(address); //QHostAddress("224.0.0.2")udpSocket->writeDatagram(QNetworkDatagram(send_data,address,port)); //QHostAddress("224.0.0.2")

操作完之后,调用相关接口关闭和释放:

void QAbstractSocket::disconnectFromHost()
void QAbstractSocket::close()
void QAbstractSocket::abort()

其中, abort 调用了 close, close 调用了 disconnectFromHost。 abort 立即关闭套接字,并丢弃写缓冲区中的所有待处理数据。close 关闭套接字的 IO,以及套接字的连接。

QUdpSocket对象实例化

QUdpSocket* m_udpSocket;
m_udpSocket = new QUdpSocket(this);

设置套接字选项

void setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
//Multicast路由层次,1表示只在同一局域网内
//组播TTL: 生存时间,每跨1个路由会减1,多播无法跨过大多数路由所以为1
//默认值是1,表示数据包只能在本地的子网中传送。
m_udpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption, 1);

QAbstractSocket::MulticastTtlOption:设置多播,即将此设置为整数可以设置IP_MULTICAST_TTL(对于多播数据报为TTL)套接字选项。后面的value就是那个整数,即为TTL值,范围为0~255之间的任何值。

QAbstractSocket::MulticastLoopbackOption:将value设置为1以启用IP_MULTICAST_LOOP(组播回环)套接字选项。即IP_MULTICAST_LOOP用于控制数据是否回送到本地的回环接口,0则禁用。

UDP信号触发
每当QAbstractSocket的状态更改时,都会发出此信号。 socketState参数是新状态。

void QAbstractSocket::stateChanged(QAbstractSocket::SocketState socketState)
connect(m_udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(onSocketStateChange(QAbstractSocket::SocketState)));

UDP通信的时候通过stateChanged信号来触发,通过对应的槽函数来触发。

QAbstractSocket::SocketState:套接字的连接状态
UnconnectedState:表示套接字没有连接,对应的默认值是0
ConnectingState:套接字正在执行主机名查找,对应的值是1
ConnectingState:套接字已开始建立连接。对应的值是2
ConnectedState:连接处于建立状态,对应值是3
BoundState:套接字绑定到地址和端口。对应值是4
ListeningState:监听状态,仅内部使用,对应值是5
ClosingState:套接字即将关闭(数据可能仍在等待写入)。对应值是6

void ExMulticast::onSocketStateChange(QAbstractSocket::SocketState socketState)
{switch (socketState) {case QAbstractSocket::UnconnectedState:m_labSocketState->setText("socket状态:UnconnectedState");break;case QAbstractSocket::HostLookupState:m_labSocketState->setText("socket状态:HostLookupState");break;case QAbstractSocket::ConnectingState:m_labSocketState->setText("socket状态:ConnectingState");break;case QAbstractSocket::ConnectedState:m_labSocketState->setText("socket状态:ConnectedState");break;case QAbstractSocket::BoundState:m_labSocketState->setText("socket状态:BoundState");break;case QAbstractSocket::ClosingState:m_labSocketState->setText("socket状态:ClosingState");break;case QAbstractSocket::ListeningState:m_labSocketState->setText("socket状态:ListeningState");break;default:m_labSocketState->setText("socket状态:其他未知状态...");break;}
}

QUdpSocket相关推荐

  1. QT的QUdpSocket类的使用

    详细说明 QUdpSocket类提供UDP套接字. UDP(用户数据报协议)是一种轻量级,不可靠,面向数据报的无连接协议.当可靠性不重要时可以使用它. QUdpSocket是QAbstractSock ...

  2. 5.关于QT中的网络编程,QTcpSocket,QUdpSocket

     1 新建一个项目:TCPServer.pro A  修改TCPServer.pro,注意:如果是想使用网络库,需要加上network SOURCES += \ TcpServer.cpp \ T ...

  3. Qt文档阅读笔记-QUdpSocket基本表述及简单实现

    目录 官方描述 博主例子 官方描述 具体总结如下(Detailed Description中): 1.UDP是轻量级,不可靠的传输协议! 2.QUdpSocket是QAbstractSocket的子类 ...

  4. QUdpSocket 4.6 严重丢包

    QT 4.6 QUdpSocket 在接收大量的数据时,有严重的丢包情况处理,应该是数据频繁接收时,来不及处理就丢包所致. 转载于:https://www.cnblogs.com/William_Fi ...

  5. Qt总结之十三:QUDPSocket详解

    前言 (一)和本文有关的博客 八大字符转换方式可参考文章:https://blog.csdn.net/Aidam_Bo/article/details/84111776 uint8_t / uint1 ...

  6. Qt之QUdpSocket定时器网络广播

    UDP(用户数据报协议)是一个轻量级的,不可靠的,面向数据报的,无连接协议.当可靠性不是很重要的时候就可以使用该协议. 程序实现功能:1.设定时间发送信息 2.服务端和客户端在同一个程序 3.可以发送 ...

  7. Upd通信之QUdpSocket的unicast单播、broadcast广播、multicast组播

    简 述: 了解Upd通信之QUdpSocket的unicast单播.broadcast广播.multicast组播,书写一个简单地例子:然后写了一个小的Qt例子,用来实现和验证它的空间的一些属性和功能 ...

  8. (QT) QUdpSocket / 在QT中通过Winsock2实现UDP通讯

    最近在编写一个网络通讯模块,需要用到QUdpSocket,但因Qt5.6以后版本放弃兼容XP系统,而不少客户因为早些购买的电脑配置低的问题,不能安装Win7以上的系统,需要的功能也并不是很多,主要用来 ...

  9. Qt网络延时测试(QTcpSocket,QUdpSocket)

    首先说明,测试不一定严谨,只是为了记录测试过程 为了能有对比性,这里采用了asio1.18.1作为服务端,分别使用qtcpsocket和asio进行测试 测试在本机测试 127.0.0.1 一.测试t ...

最新文章

  1. 支付宝蚂蚁森林合种树,2-4天领证,1/2号车满员,3号车成立
  2. 李彦宏要给百度全员涨薪 连实习生都雨露均沾 :再没有行动,人都要被字节跳动给挖光了。
  3. 科大星云诗社动态20201130
  4. Magicodes.IE 2.5.4.2发布
  5. 基于域名的apache服务器
  6. linux 谷歌浏览器设置代理_linux下chrome+Proxy Switchy+ssh和firefox+autoproxy+ssh | 学步园...
  7. Redis的实现原理
  8. 敏捷开发免费管理工具——火星人预览之五:常见问题问答
  9. matlab2c使用c++实现matlab函数系列教程-intersect函数
  10. 让serialversionUID自动生成方法
  11. JAVA里的jsp网页背景_Java-带CSS的JSP不显示背景图像
  12. adc0808温度换算公式_多路温度采集与控制(C51、ADC0808)
  13. PCBA加工为什么要做首件检测?
  14. NGOD client 完成感想
  15. 阿里云开发笔记01——CuteFTP使用方法
  16. sqlserver排序规则介绍以及修改
  17. 域名检测工具-免费老域名扫描软件下载
  18. Manjaro快速上手指南-微信、TIM/QQ、网易云音乐、WPS等等
  19. UserWarning: Glyph 20809 (\N{CJK UNIFIED IDEOGRAPH-5149}) missing from current font解决方法
  20. 【Ubuntu】更新系统时间

热门文章

  1. SQLite内部机制和新特性
  2. php 循环table,php table循环 问题很简单 求帮助
  3. matlab plot 坐标轴标注,Matlab绘图坐标轴的设置教程
  4. mysql5.7复制集_技术分享 | 克隆:更优雅的创建 MySQL 实例副本
  5. HDU 2588 GCD
  6. 微信JS-SDK开发 入门指南
  7. VB 泛型 T 应用
  8. MariaDB Centos7 下安装MariaDB
  9. LeetCode(389)——找不同(JavaScript)
  10. LeetCode(566)——重塑矩阵(JavaScript)