QT Udp广播实现设备发现
测试环境
本文选用pc1作为客户端,pc2,以及一台虚拟机作为服务端。
- pc1,pc2(客户端):

- 虚拟机(服务端):

客户端
- 原理:客户端通过发送广播消息信息到ip:255.255.255.255(QHostAddress::Broadcast),局域网内的所有设备收到该消息回复客户端即可。客户端通过收到的回复统计当前有哪些设备在线。
- 获取到本地的IP,getLocalIP函数获取到过滤了虚拟机网卡以及本地回环网卡后的ip地址。

#include "udpclient.h"
#include <QDebug>
#include <QHostInfo>
#include <QNetworkInterface>
#include <iostream>udpClient::udpClient(QObject *parent) : QObject(parent)
{QString localIp = getLocalIP();udpSocket = new QUdpSocket;udpSocket->bind(QHostAddress(localIp),2001);connect(udpSocket,&QUdpSocket::readyRead,this,&udpClient::processData);}QString udpClient::getLocalIP() {QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();foreach (const QNetworkInterface &interface, interfaces) {QList<QNetworkAddressEntry> entries = interface.addressEntries();qDebug()<<"name:"<<interface.humanReadableName()<<endl;if(interface.humanReadableName().contains("Loopback") ||interface.humanReadableName().contains("VMware Network Adapter")){continue;}foreach (const QNetworkAddressEntry &entry, entries) {if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) {qDebug() << "Local IP Address: " << entry.ip().toString()<< endl;}}}return QString();
}udpClient::~udpClient()
{if(udpSocket){delete udpSocket;}
}void udpClient::sendBroadCast()
{QByteArray datagram = "Device Discovery";udpSocket->writeDatagram(datagram,QHostAddress::Broadcast,8888);
}void udpClient::processData()
{while(udpSocket->hasPendingDatagrams()){QByteArray datagram;datagram.resize(udpSocket->pendingDatagramSize());QHostAddress sender;quint16 senderPort;udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);qDebug() << "Received response from: " << sender.toString()<<"port:"<<senderPort << endl;}
}
服务端
#include "udpserver.h"
#include <iostream>udpServer::udpServer(QObject *parent) : QObject(parent)
{udpSocket = new QUdpSocket(this);udpSocket->bind(QHostAddress::Any, 8888);connect(udpSocket, &QUdpSocket::readyRead, this, &udpServer::processPendingDatagrams);}void udpServer::processPendingDatagrams()
{while (udpSocket->hasPendingDatagrams()) {QByteArray datagram;datagram.resize(udpSocket->pendingDatagramSize());QHostAddress sender;quint16 senderPort;udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);std::cout << "Received discovery message: " << datagram.data() << std::endl;QByteArray response = "Device Found";udpSocket->writeDatagram(response, sender, senderPort);}
}
输出效果


优化
- 对客户端增加定时器,同时将客户端对象移动到一个线程中,这样就可以定时轮询设备发现了。
#include "udpclient.h"
#include <QDebug>
#include <QHostInfo>
#include <QNetworkInterface>
#include <iostream>
#include <QTimer>
#include <QThread>udpClient::udpClient(QObject *parent) : QObject(parent)
{qDebug()<<"thread id1:"<<QThread::currentThreadId()<<endl;
}void udpClient::createSocket()
{qDebug()<<"thread id2:"<<QThread::currentThreadId()<<endl;QString localIp = getLocalIP();udpSocket = new QUdpSocket;udpSocket->bind(QHostAddress(localIp),2001);connect(udpSocket,&QUdpSocket::readyRead,this,&udpClient::processData);
}QString udpClient::getLocalIP() {QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();foreach (const QNetworkInterface &interface, interfaces) {QList<QNetworkAddressEntry> entries = interface.addressEntries();qDebug()<<"name:"<<interface.humanReadableName()<<endl;if(interface.humanReadableName().contains("Loopback") ||interface.humanReadableName().contains("VMware Network Adapter")){continue;}foreach (const QNetworkAddressEntry &entry, entries) {if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) {qDebug() << "Local IP Address: " << entry.ip().toString()<< endl;}}}return QString();
}udpClient::~udpClient()
{if(udpSocket){delete udpSocket;}
}void udpClient::sendBroadCast()
{QByteArray datagram = "Device Discovery";udpSocket->writeDatagram(datagram,QHostAddress::Broadcast,8888);qDebug()<<"sendBroadCast,thread id:"<<QThread::currentThreadId()<<endl;
}void udpClient::processData()
{while(udpSocket->hasPendingDatagrams()){QByteArray datagram;datagram.resize(udpSocket->pendingDatagramSize());QHostAddress sender;quint16 senderPort;udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);result.push_back(IpInfo(sender.toString(),senderPort));qDebug() << "Received response from: " << sender.toString()<<"port:"<<senderPort << endl;}
}void tcpConnect(QString& ip, quint16 port)
{}#include "widget.h"
#include "ui_widget.h"
#include <QTimer>
#include <QEventLoop>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);client = new udpClient;connect(ui->pushButton,&QPushButton::clicked,client,&udpClient::sendBroadCast);thread = new QThread;connect(thread,&QThread::finished,client,&QObject::deleteLater);connect(thread,&QThread::started,client,&udpClient::createSocket);client->moveToThread(thread);timer = new QTimer(this);connect(timer,&QTimer::timeout,client,&udpClient::sendBroadCast);timer->setInterval(500);thread->start();
// QEventLoop loop;
// QTimer::singleShot(500,&loop,&QEventLoop::quit);
// loop.exec();timer->start();qDebug()<<"thread id:"<<QThread::currentThreadId()<<endl;
}Widget::~Widget()
{delete ui;thread->quit();thread->wait();delete thread;thread=nullptr;
}相关文章:
QT Udp广播实现设备发现
测试环境 本文选用pc1作为客户端,pc2,以及一台虚拟机作为服务端。 pc1,pc2(客户端): 虚拟机(服务端): 客户端 原理:客户端通过发送广播消息信息到ip:255.255.255.255(QHostAddress::Broadcast),局域网…...
PyTorch 统计属性-Tensor基本操作
最小 min, 最大 max, 均值 mean,累加 sum,累乘 prod … >>> a torch.arange(0,8).view(2,4).float() >>> a tensor([[0., 1., 2., 3.],[4., 5., 6., 7.]])>>> a.min() ## 最小值:tensor(0.) >>> a.ma…...
波拉西亚战记加速器 台服波拉西亚战记免费加速器
波拉西亚战记是一款新上线的MMORPG游戏,游戏内我们有多个角色职业可以选择,可以体验不同的战斗流派玩法,开放式的地图设计,玩家可以自由的进行探索冒险,寻找各种物资。各种随机事件可以触发,让玩家的冒险过…...
Mocha + Chai 测试环境配置,支持 ES6 语法
下面是一个完整的 Mocha Chai 测试环境配置,支持 ES6 语法。我们将使用 Babel 来转译 ES6 代码。 步骤一:初始化项目 首先,在项目目录中运行以下命令来初始化一个新的 Node.js 项目: npm init -y步骤二:安装必要的…...
华为网络设备攻击防范
畸形报文攻击防范 攻击行为 畸形报文攻击是通过向交换机发送有缺陷的IP报文,使得交换机在处理这样的IP包时会出现崩溃,给交换机带来损失。 畸形报文攻击主要有如下几种: 没有IP载荷的泛洪攻击 IGMP空报文攻击 LAND攻击 Smurf攻击 TCP标…...
RK3588开发笔记-100M网口自协商成1000M网口
目录 前言 一、问题描述 二、原理图连接 三、解决方法 总结 前言 在进行RK3588开发过程中,遇到一个令人困惑的问题:在使用RTL8211F-CG phy芯片出来的100M网口在自协商后连接速率变成了1000M。这篇博客将详细记录这个问题的产生、排查过程以及最终的解决方案,希望能对遇到…...
Python第二语言(十三、PySpark实战)
目录 1.开篇 2. PySpark介绍 3. PySpark基础准备 3.1 PySpark安装 3.2 掌握PySpark执行环境入口对象的构建 3.3 理解PySpark的编程模型 4. PySpark:RDD对象数据输入 4.1 RDD对象概念:PySpark支持多种数据的输入,完成后会返回RDD类的对…...
《阅读的方法》读后感——超越期待的收获
当我翻开这本书的扉页时,未曾料到它会给我带来如此深远的启示和收获。依照推荐序言中的指引,我随意翻阅、精心选读,每一次都如同打开一扇新的窗户,让我窥见不同领域的智慧和美好。 等地铁时、临睡前随便读点什么,有什么…...
算法训练营第五十八天 | LeetCode 392 判断子序列、卡码网模拟美团笔试第一、二、三题(300/500有待提高)
卡码网图论更新了可以去看看,模拟笔试第四题就是深搜/广搜还不太会 LeetCode 392 判断子序列 其实就是最长公共子序列翻版 代码如下: class Solution {public boolean isSubsequence(String s, String t) {int[][] dp new int[s.length() 1][t.lengt…...
Sa-Token鉴权与网关服务实现
纠错: 在上一部分里我完成了微服务框架的初步实现,但是先说一下之前有一个错误,就是依赖部分 上次的学习中我在总的父模块下引入了spring-boot-dependencies(版本控制)我以为在子模块下就不需要再引用了,…...
企事业单位安全生产月活动怎样向媒体投稿?
作为一名单位的信息宣传员,我肩负着将每一次重要活动的精彩瞬间转化为文字,向外界传递我们单位声音的重任。初入此行时,我满怀热情,坚信通过传统的方式——电子邮件投稿,能够有效地将我们的故事传播出去。然而,现实却给我上了生动的一课。 记得在筹备“安全生产月”活动的宣传时…...
MySQL8.0默认TCP端口介绍
1、本文内容 选择题TCP/IPMySQL 8.0 的默认TCP端口show variables查看总结 2、选择题 A、3306 B、33060 C、33062 D、33063 3、TCP/IP TCP/IP(Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议)是指能够在多个不同…...
Javaweb避坑指北(持续更新)
内容较多可按CtrlF搜索 0.目录 1.获取插入数据后自增长主键的值 2.Controller中返回给ajax请求字符串/json会跳转到xxx.jsp 3.ajax请求获得的json无法解析 4.在Controller中使用ServletFileUpload获取的上传文件为null 5.莫名其妙报service和dao里方法的错误 6.ajax请求拿…...
Web前端知道:深入探索与无尽挑战
Web前端知道:深入探索与无尽挑战 Web前端,这个看似简单却实则深不可测的领域,一直以来都吸引着无数开发者投入其中。在这个充满未知与可能的世界里,我们既是探索者,也是挑战者。本文将从四个方面、五个方面、六个方面…...
QT调用vs2019生成的c++动态库
QT调用vs2019生成的c动态库 dll库的创建方法: VS2019创建c动态链接库dll与调用方法-CSDN博客 加减法示范: 头文件 // 下列 ifdef 块是创建使从 DLL 导出更简单的 // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 DLL3_EXPORTS // 符号编…...
C语言TC中有⼏个画线函数?怎么使⽤?
一、问题 C语⾔中画线的函数好像不⽌ line( )⼀个,那么除了 line( ) ,还有哪些画线函数?怎么使⽤? 二、解答 TC中有3种画线的函数,共语法格式如下。 void far line(int x0, int y0, int xl, int y1); void far linet…...
掌握WhoisAPI,提升域名管理的效率
在互联网时代,域名管理是网站运营中非常重要的一环。通过域名,我们能够轻松访问和识别不同的网站。然而,域名的注册和管理也是一项复杂的任务,特别是对于大规模拥有许多域名的企业来说。为了提升域名管理的效率,我们可…...
Docker与Docker-Compose详解
1、Docker是什么? 在计算机中,虚拟化(英语: Virtualization) 是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍&…...
微服务之熔断器
1、高并发带来的问题 在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用,但是由于网络原因 或者自身的原因,服务并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会…...
【高校科研前沿】北京大学赵鹏军教授团队在Nature Communications发文:揭示城市人群移动的空间方向性
文章简介 论文名称:Unravelling the spatial directionality of urban mobility 第一作者及单位:赵鹏军(教授|第一作者|北京大学)&王浩(博士生|共同一作|北京大学); 通讯作者及单位:赵鹏军…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险
C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...
手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
恶补电源:1.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...
41道Django高频题整理(附答案背诵版)
解释一下 Django 和 Tornado 的关系? Django和Tornado都是Python的web框架,但它们的设计哲学和应用场景有所不同。 Django是一个高级的Python Web框架,鼓励快速开发和干净、实用的设计。它遵循MVC设计,并强调代码复用。Django有…...
