【Qt】系统相关——多线程、Qt多线程介绍、常用函数、线程安全、网络、UDP Socket、TCP Socket
文章目录
- Qt
- 系统相关
- 1. 多线程
- 1.1 Qt多线程介绍
- 1.2 常用函数
- 1.3 线程安全
- 2. 网络
- 2.1 UDP Socket
- 2.2 TCP Socket
Qt

系统相关
1. 多线程
1.1 Qt多线程介绍
QThread 代表一个在应用程序中可以独立控制的线程,它还可以和进程中的其他线程共享数据。QThread 对象管理程序中的一个控制线程。
1.2 常用函数
| 函数 / 信号名 | 功能描述 |
|---|---|
| run() | 线程的入口函数,包含线程执行的代码逻辑 |
| start() | 调用 run () 开始执行线程,根据优先级调度,若线程已运行则不做任何事 |
| currentThread() | 返回指向管理当前执行线程的 QThread 指针 |
| isRunning() | 线程正在运行则返回 true,否则返回 false |
| sleep() | 使线程休眠,单位为秒 |
| msleep() | 使线程休眠,单位为毫秒 |
| usleep() | 使线程休眠,单位为微秒 |
| wait() | 阻塞线程,直到关联线程完成执行(从 run () 返回,若已完成或未启动则返回 true)或达到指定时间(超时返回 false,默认 ULONG_MAX 表示永远等待),类似 POSIX pthread_join () 功能 |
| terminate() | 终止线程执行,是否立即终止取决于操作系统调度策略,之后建议用 wait () |
| finished() | 线程结束时发出此信号,可用于线程清理工作 |
timethread.h
#ifndef TIMETHREAD_H
#define TIMETHREAD_H#include <QThread>class TimeThread : public QThread
{Q_OBJECTpublic:TimeThread();void run(); //线程任务函数signals:void sendTime(QString Time); //声明信号函数
};#endif // TIMETHREAD_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <timethread.h> //添加头文件
#include <QLabel>QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void on_btn_clicked();void showTime(QString Time);private:QLabel* label;Ui::Widget *ui;TimeThread t; //定义线程对象
};
#endif // WIDGET_H
timethread.cpp
#include "timethread.h"#include <QTime>
#include <QDebug>
#include <QString>TimeThread::TimeThread() {}void TimeThread::run()
{while(1){QString time = QTime::currentTime().toString("hh:mm:ss");qDebug() << time;emit sendTime(time); //发送信号sleep(1);}
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"#include "timethread.h"
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
#include <QSpacerItem>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QGridLayout* layout=new QGridLayout();label=new QLabel(this);label->setFixedSize(500,300);label->setFrameShape(QFrame::Box);label->setText("SSSSSSSSSSSSSSSSSSSS");QPushButton* btn=new QPushButton(this);btn->setFixedSize(100,50);btn->setText("确定");layout->addWidget(label,0,0,1,1);layout->addWidget(btn,1,0,1,1);this->setLayout(layout);connect(&t,&TimeThread::sendTime,this,&Widget::showTime);connect(btn,&QPushButton::clicked,this,&Widget::on_btn_clicked);
}Widget::~Widget()
{delete ui;
}void Widget::on_btn_clicked()
{t.start(); //开启线程
}void Widget::showTime(QString Time)
{label->setText(Time);
}


| 连接类型 | 说明 | 适用场景 | 注意事项 |
|---|---|---|---|
| Qt::AutoConnection | 根据信号和槽所在线程自动选择连接类型,同线程用 Qt::DirectConnection,不同线程用 Qt::QueuedConnection | 通用场景 | 无 |
| Qt::DirectConnection | 信号发出时,槽函数立即在同线程执行 | 信号和槽在同一线程 | 注意线程安全性 |
| Qt::QueuedConnection | 信号发出时,槽函数插入接收对象所属线程事件队列,下次事件循环执行 | 信号和槽在不同线程 | 确保线程安全 |
| Qt::BlockingQueuedConnection | 与 Qt::QueuedConnection 类似,但发送信号线程会阻塞至槽函数执行完毕 | 需等待槽函数执行完再继续的场景 | 注意可能引起线程死锁 |
| Qt::UniqueConnection | 可与其他连接类型位或组合使用 | 用于保证相同信号和槽之间只有一个连接 | 无 |
1.3 线程安全
实现线程互斥和同步常用的类有:
• 互斥锁:QMutex、QMutexLocker
• 条件变量:QWaitCondition
• 信号量:QSemaphore
• 读写锁:QReadLocker、QWriteLocker、QReadWriteLock
QMutex(互斥锁)
| 函数 | 功能描述 |
|---|---|
| QMutex() | 创建互斥锁。 |
| ~QMutex() | 销毁互斥锁。 |
| lock() | 获取锁,阻塞等待。 |
| tryLock() | 尝试获取锁,不阻塞。 |
| unlock() | 释放锁。 |
| recursiveLock()(递归锁) | 获取递归锁。 |
| tryRecursiveLock() | 尝试获取递归锁。 |
| unlockRecursive() | 释放递归锁。 |
QMutexLocker(互斥锁辅助类)
| 函数 | 功能描述 |
|---|---|
| QMutexLocker(QMutex * mutex) | 构造时尝试获取互斥锁。 |
| ~QMutexLocker() | 析构时释放互斥锁。 |
| relock() | 重新获取互斥锁。 |
| unlock() | 手动释放互斥锁。 |
QWaitCondition(条件变量)
| 函数 | 功能描述 |
|---|---|
| QWaitCondition() | 创建条件变量。 |
| ~QWaitCondition() | 销毁条件变量。 |
| wait(QMutex * mutex) | 线程等待,释放互斥锁,被唤醒后重新获取。 |
| wait(QMutex * mutex, ulong time) | 等待指定时间,超时返回 false。 |
| wakeOne() | 唤醒一个等待线程。 |
| wakeAll() | 唤醒所有等待线程。 |
QSemaphore(信号量)
| 函数 | 功能描述 |
|---|---|
| QSemaphore(int n = 0) | 创建信号量,设置初始值。 |
| ~QSemaphore() | 销毁信号量。 |
| acquire(int n = 1) | 获取 n 个资源,阻塞等待。 |
| tryAcquire(int n = 1) | 尝试获取 n 个资源,不阻塞。 |
| release(int n = 1) | 释放 n 个资源。 |
QReadLocker(读写锁 - 读操作辅助类)
| 函数 | 功能描述 |
|---|---|
| QReadLocker(QReadWriteLock * lock) | 构造时获取读锁。 |
| ~QReadLocker() | 析构时释放读锁。 |
| relock() | 重新获取读锁。 |
| unlock() | 手动释放读锁。 |
QWriteLocker(读写锁 - 写操作辅助类)
| 函数 | 功能描述 |
|---|---|
| QWriteLocker(QReadWriteLock * lock) | 构造时获取写锁。 |
| ~QWriteLocker() | 析构时释放写锁。 |
| relock() | 重新获取写锁。 |
| unlock() | 手动释放写锁。 |
QReadWriteLock(读写锁)
| 函数 | 功能描述 |
|---|---|
| QReadWriteLock() | 创建读写锁。 |
| ~QReadWriteLock() | 销毁读写锁。 |
| lockForRead() | 获取读锁,阻塞。 |
| tryLockForRead() | 尝试获取读锁,不阻塞。 |
| unlock() | 释放锁。 |
| lockForWrite() | 获取写锁,阻塞。 |
| tryLockForWrite() | 尝试获取写锁,不阻塞。 |
2. 网络
2.1 UDP Socket
QUdpSocket
| 名称 | 类型 | 说明 | 对标原生 API |
|---|---|---|---|
| bind(const QHostAddress&, quint16) | 方法 | 绑定指定的端口号 | bind |
| receiveDatagram() | 方法 | 返回 QNetworkDatagram,读取一个 UDP 数据报 | recvfrom |
| writeDatagram(const QNetworkDatagram&) | 方法 | 发送一个 UDP 数据报 | sendto |
| readyRead | 信号 | 在收到数据并准备就绪后触发 | 无(类似 IO 多路复用的通知机制) |
QNetworkDatagram
| 名称 | 类型 | 说明 | 对标原生 API |
|---|---|---|---|
| QNetworkDatagram(const QByteArray&, const QHostAddress&, quint16) | 构造函数 | 通过 QByteArray、目标 IP 地址、目标端口号构造一个 UDP 数据报,通常用于发送数据时 | 无 |
| data() | 方法 | 获取数据报内部持有的数据,返回 QByteArray | 无 |
| senderAddress() | 方法 | 获取数据报中包含的对端的 IP 地址 | 无(recvfrom 包含该功能) |
| senderPort() | 方法 | 获取数据报中包含的对端的端 | 无(recvfrom 包含该功能) |
服务端:
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QUdpSocket>QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();QUdpSocket* socket;void processRequest();QString process(const QString&);private:Ui::Widget *ui;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"#include <QMessageBox>
#include <QUdpSocket>
#include <QNetworkDatagram>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 1. 设置窗⼝标题this->setWindowTitle("服务器");// 2. 实例化 socketsocket = new QUdpSocket(this);// 3. 连接信号槽, 处理收到的请求connect(socket, &QUdpSocket::readyRead, this, &Widget::processRequest);// 4. 绑定端⼝bool ret = socket->bind(QHostAddress::Any, 9090);if (!ret) {QMessageBox::critical(nullptr, "服务器启动出错", socket->errorString());return;}
}Widget::~Widget()
{delete ui;
}void Widget::processRequest()
{// 1. 读取请求const QNetworkDatagram& requestDatagram = socket->receiveDatagram();QString request = requestDatagram.data();// 2. 根据请求计算响应const QString& response = process(request);// 3. 把响应写回到客户端QNetworkDatagram responseDatagram(response.toUtf8(),requestDatagram.senderAddress(), requestDatagram.senderPort());socket->writeDatagram(responseDatagram);// 显示打印日志QString log = "[" + requestDatagram.senderAddress().toString() + ":" +QString::number(requestDatagram.senderPort())+ "] req: " + request + ", resp: " + response;ui->listWidget->addItem(log);
}QString Widget::process(const QString& request)
{return request;
}
客户端:
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QUdpSocket>QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_pushButton_clicked();private:Ui::Widget *ui;// 创建 socket 成员QUdpSocket* socket;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"#include <QNetworkDatagram>// 提前定义好服务器的 IP 和 端⼝
const QString& SERVER_IP = "127.0.0.1";
const quint16 SERVER_PORT = 9090;Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 1. 设置窗口名字this->setWindowTitle("客户端");// 2. 实例化 socketsocket = new QUdpSocket(this);connect(socket, &QUdpSocket::readyRead, this, [=]() {const QNetworkDatagram responseDatagram = socket->receiveDatagram();QString response = responseDatagram.data();ui->listWidget->addItem(QString("服务器说: ") + response);});
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{// 1. 获取到输⼊框的内容const QString& text = ui->lineEdit->text();// 2. 构造请求数据QNetworkDatagram requestDatagram(text.toUtf8(), QHostAddress(SERVER_IP),SERVER_PORT);// 3. 发送请求socket->writeDatagram(requestDatagram);// 4. 消息添加到列表框中ui->listWidget->addItem("客⼾端说: " + text);// 5. 清空输⼊框ui->lineEdit->setText("");
}

2.2 TCP Socket
QTcpServer
| 名称 | 类型 | 说明 | 对标原生 API |
|---|---|---|---|
| listen(const QHostAddress&, quint16 port) | 方法 | 绑定指定地址和端口号并开始监听 | bind 和 listen |
| nextPendingConnection() | 方法 | 从系统获取已建立好的 tcp 连接,返回 QTcpSocket 用于和客户端通信 | accept |
| newConnection | 信号 | 新客户端连接建立好后触发 | 无(类似 IO 多路复用通知机制) |
QTcpSocket
| 名称 | 类型 | 说明 | 对标原生 API |
|---|---|---|---|
| readAll() | 方法 | 读取接收缓冲区所有数据,返回 QByteArray | read |
| write(const QByteArray&) | 方法 | 将数据写入 socket | write |
| deleteLater | 方法 | 标记 socket 对象无效,在下个事件循环析构释放 | 无(类似 “半自动垃圾回收”) |
| readyRead | 信号 | 数据到达且准备就绪时触发 | 无(类似 IO 多路复用通知机制) |
| disconnected | 信号 | 连接断开时触发 | 无(类似 IO 多路复用通知机制) |
相关文章:
【Qt】系统相关——多线程、Qt多线程介绍、常用函数、线程安全、网络、UDP Socket、TCP Socket
文章目录 Qt系统相关1. 多线程1.1 Qt多线程介绍1.2 常用函数1.3 线程安全 2. 网络2.1 UDP Socket2.2 TCP Socket Qt 系统相关 1. 多线程 1.1 Qt多线程介绍 QThread 代表一个在应用程序中可以独立控制的线程,它还可以和进程中的其他线程共享数据。QThread 对象管理…...
1GS/s 4通道14bit PCIE采集卡
1GS/s 4通道14bit PCIE采集卡是一款同时具备直流耦合程控放大器和双极性宽带信号输入的高速数据采集卡。板载FPGA具备实时信号处理能力,这些特性使其成为激光雷达、光纤传感、粒子物理等应用领域进行信号采集和分析的理想工具。提供快速的PCI Express 3.0 x8数据传输…...
动态IP是什么?
随着互联网成为人们生活的重要组成部分,以信息传递为主导的时代种,网络连接质量对我们的工作效率、学习进度以及娱乐体验等方面都有很大影响。 动态IP,作为网络连接中的一种重要IP代理形式,越来越受到用户的欢迎。本文将深入解析…...
51单片机完全学习——红外遥控
一、红外接收模块原理 红外接收头内部本身有一个反相,意思就是:平时发送方无信号时接收到的是1,发送方有发送载波时接收头引脚输出的是0,写代码的时候注意这一点。红外协议,你也可以理解成,他对0和1重新做…...
群控系统服务端开发模式-应用开发-业务架构逻辑开发BaseAPI
一、加密工具开发 首先在根目录下extend文件中创建Encipher文件夹,用于专门开发加解密工具,新建RSA算法控制器并命名为Encrypt.php。然后在根目录下config文件夹中创建rsa.php文件,用于配置RSA算法参数。 1、秘钥生成算法 <?php /*** RS…...
【AI日记】24.10.27 了解AI的未来
【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 工作 工作1 内容:挑选AI大佬的访谈,跳着看了几个时间:2小时 工作2 内容:OpenAI Sam Altman最新访谈:GPT-4o和AI未来 2024.5时间:2小时收…...
【时间之外】IT人求职和创业应知【19】
认知决定你的赚钱能力。以下是今天可能影响你求职和创业的热点新闻: 今日关键字:深圳长沙(备注:我都没有去过) 2024中国(长沙)民营企业科技创新发展大会召开 内容概述: 2024年10月…...
MOE混合专家模型总结(面试)
目录 1. MOE介绍 2.MOE出现的背景 3.有哪些MOE模型 4.门控网络或路由 5.为什么门控网络要引入噪声 6.如何均衡专家间的负载 7.“专家”指什么 8.专家的数量对预训练有何影响 9.什么是topk门控 10.MOE模型的主要特点 11.MOE和稠密模型的对比 12.MOE的优势 13.MOE的挑…...
第8次CCF CSP认证真题解
1、最大波动 题目链接:https://sim.csp.thusaac.com/contest/8/problem/0 100分代码: #include <iostream> #include <algorithm> using namespace std; int main(int argc, char *argv[]) {int n;cin >> n;int a[1010];for(int i …...
2024昆明ICPC A. Two-star Contest(直观命名+详细注释)
Problem - A - Codeforces 思路: 按照等级排序,维护同等级最大评分,每个等级的总评分至少比其第前一个等级的最大评分大1分 吐槽: 思路不难,但坑好多,感觉全踩了一遍 坑:(按解决…...
【算法刷题指南】双指针
🌈个人主页: 南桥几晴秋 🌈C专栏: 南桥谈C 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据…...
HTML,CSS,JavaScript三件套
前言 1.HTML 就是用来写网页的 就是超文本标记语言 1.1快速入门 标签是根标签,就是开始的地方 head就是头,加载一些资源信息,和展示title标题的地方,比如html快速入门那几个字就是title标题标签 body是身体,就是正…...
react 总结+复习+应用加深
文章目录 一、React生命周期1. 挂载阶段(Mounting)补充2. 更新阶段(Updating)补充 static getDerivedStateFromProps 更新阶段应用补充 getSnapshotBeforeUpdate3. 卸载阶段(Unmounting) 二、React组件间的…...
关于 API
关于 API $set 问法:有没有遇到过数据更新了但视图没有更新的情况? <template><div>{{arr}}<button click"btn"></button></div> </template><script> export default {name:"Home"da…...
第15次CCF CSP真题解
1、小明上学 题目链接:https://sim.csp.thusaac.com/contest/15/problem/0 本题是模拟红绿灯计时的题,根据红绿灯转换规则可知,红灯后面通常是绿灯,绿灯后面是黄灯,黄灯过后又是红灯。根据题意,当k 0时&…...
STM32硬件平台
STM32 系列是 STMicroelectronics 设计的高度灵活、广泛应用的微控制器(MCU)系列,支持从低功耗应用到高性能处理的需求,适用于工业、汽车、消费电子和物联网等广泛领域。STM32 系列具有广泛的硬件种类和丰富的功能,以下…...
一文讲明白大模型分布式逻辑(从GPU通信原语到Megatron、Deepspeed)
1. 背景介绍 如果你拿到了两台8卡A100的机器(做梦),你的导师让你学习部署并且训练不同尺寸的大模型,并且写一个说明文档。你意识到,你最需要学习的就是关于分布式训练的知识,因为你可是第一次接触这么多卡…...
【人工智能-初级】第6章 决策树和随机森林:浅显易懂的介绍及Python实践
文章目录 一、决策树简介二、决策树的构建原理2.1 决策树的优缺点优点缺点 三、随机森林简介3.1 随机森林的构建过程3.2 随机森林的优缺点优点缺点 四、Python实现决策树和随机森林4.1 导入必要的库4.2 加载数据集并进行预处理4.3 创建决策树模型并进行训练4.4 可视化决策树4.5…...
时间序列预测(九)——门控循环单元网络(GRU)
目录 一、GRU结构 二、GRU核心思想 1、更新门(Update Gate):决定了当前时刻隐藏状态中旧状态和新候选状态的混合比例。 2、重置门(Reset Gate):用于控制前一时刻隐藏状态对当前候选隐藏状态的影响程度。…...
李东生牵手通力股份IPO注册卡关,三年近10亿“清仓式分红”引关注
《港湾商业观察》施子夫 9月27日,通力科技股份有限公司(以下简称,通力股份)再度提交了注册申请,实际上早在去年11月6日公司已经提交过注册,看起来公司注册环节面临卡关。公开信息显示,通力股份…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
