当前位置: 首页 > news >正文

PC端QT实现mqtt客户端发布和订阅

在Windows11-64位系统下使用QT开发桌面应用程序,实现mqtt客户端的发布和订阅功能。

需求:

mqtt代理服务器 --mosquitto;

mqtt客户端工具 -- mqtt.fx;

qtcreator开发工具 -- qtcreator6.8.2版本;

过程:

Windows下MQTT服务器搭建

安装mosquitto-1.6.9-install-windows-x64.exe,全部按默认安装即可,路径可以自己修改。

安装后在安装路径会有一个名为mosquitto.conf的配置文件,按照如下方式进行配置,默认端口1883。

修改allow_anonymous为true以允许主机匿名访问。

在mosquitto安装目录下启用终端(cmd),执行命令启动mosquitto服务

windows的mosquitto刚启动时候不会输出任何信息,只要能启动,就代表成功了。

如果想查看调试信息,那么就把log_type的配置项打开。

MQTT客户端工具使用

在客户端发布过程中,可以通过MQTT服务端终端查看相关debug,如下图:

QT开发

由于使用的qt6.8.2版本,使用mqtt驱动库需要重新编译,在安装插件时需要选择source

这边已经安装过,实际安装可能需要几个G的安装内存,安装过程中会出现一些下载错误的情况,不用管,直接重新下载就可以。

安装好后,在qt安装目录下能看到qtmqtt文件夹,那么就说明source源码安装成功。

接下来需要编译MQTT源码,需要CMake和Ninja两个命令。

执行cmake --version和ninja --version查看版本号,能查看说明安装成功。注意需要更新环境变量path。

CSDN上有比较详细的编译MQTT驱动方式,这里简单介绍下。

mkdir build
cd build
cmake -G "Ninja" -DCMAKE_PREFIX_PATH=C:/Qt/6.8.2/msvcxxx_64 ../
ninja
ninja install

有的情况下,可能需要配置环境变量path

一般这样就能完成mqtt编译,打开qt工程,如果出现以下输出,说明工程没有获取到mqtt驱动,再仔细检查下,还有qt工程的.pro中增加mqtt模块。

QT开发UI界面

QT代码
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);tcpSocket = new QTcpSocket(this);connect(tcpSocket,SIGNAL(readyRead()),this,SLOT(readMessage()));//连接信号和相应槽函数connect(tcpSocket,SIGNAL(connected()),this,SLOT(sendMessage()));connect(tcpSocket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(displayError(QAbstractSocket::SocketError)));connect(ui->pushButton_recv,SIGNAL(clicked()),this,SLOT(pushButton_recv_clicked()));connect(ui->pushButton_del,SIGNAL(clicked()),this,SLOT(pushButton_del_clicked()));//连接mqttconnect(&mqtt_client, &QMqttClient::connected, [&]() {ui->pushButton_mqttconnect->setText("mqtt断开");ui->lineEdit_host->setEnabled(false);ui->lineEdit_port->setEnabled(false);ui->pushButton_mqttrecv->setEnabled(true);ui->pushButton_mqttsend->setEnabled(true);});//断开mqttconnect(&mqtt_client, &QMqttClient::disconnected, [&]() {ui->pushButton_mqttconnect->setText("mqtt连接");ui->lineEdit_host->setEnabled(true);ui->lineEdit_port->setEnabled(true);});// 检测连接状态// connect(&mqtt_client, &QMqttClient::stateChanged, [&](QMqttClient::ClientState state) {//     if (state == QMqttClient::Connected) {//         //qDebug() << "Connected to MQTT broker!";//         ui->textEdit_db->append("Connected to MQTT broker!"+ui->lineEdit_host->text()+":"+ui->lineEdit_port->text());//     } else if (state == QMqttClient::Disconnected) {//         //qDebug() << "Disconnected from MQTT broker!";//         ui->textEdit_db->append("Disconnected from MQTT broker!"+ui->lineEdit_host->text()+":"+ui->lineEdit_port->text());//     } else if (state == QMqttClient::Connecting) {//         //qDebug() << "Connecting to MQTT broker...";//         ui->textEdit_db->append("Connecting to MQTT broker...!"+ui->lineEdit_host->text()+":"+ui->lineEdit_port->text());//     }// });// 连接错误时的槽函数connect(&mqtt_client, &QMqttClient::errorChanged, [&](QMqttClient::ClientError error) {//qDebug() << "Error occurred:" << error;ui->textEdit_db->append("Error occurred: "+QString::fromStdString(std::to_string(error)));});//接收消息connect(&mqtt_client, &QMqttClient::messageReceived, [&](const QByteArray &message, const QMqttTopicName &topic) {ui->textEdit_db->append("mqtt_recv: "+topic.name()+":"+message);});connect(ui->pushButton_mqttconnect,SIGNAL(clicked()),this,SLOT(pushButton_mqttconnect_clicked()));connect(ui->pushButton_mqttrecv,SIGNAL(clicked()),this,SLOT(pushButton_mqttrecv_clicked()));connect(ui->pushButton_mqttsend,SIGNAL(clicked()),this,SLOT(pushButton_mqttsend_clicked()));ui->pushButton_mqttrecv->setEnabled(false);ui->pushButton_mqttsend->setEnabled(false);// 设置 QTextEdit 无法选择文本ui->textEdit_db->setTextInteractionFlags(Qt::NoTextInteraction);
}Widget::~Widget()
{delete ui;
}void Widget::connect_db()
{QStringList drivers = QSqlDatabase::drivers();foreach(QString driver, drivers) {ui->textEdit_db->append(driver);}ui->textEdit_db->append("test.");db = QSqlDatabase::addDatabase("QMYSQL");db.setHostName("118.31.2.73");db.setPort(3306); // MySQL的默认端口是3306db.setDatabaseName("test_db");db.setUserName("root");db.setPassword("123456");if (!db.open()) {ui->textEdit_db->append("Error: Unable to connect to the database.");return;}//ui->pushButton_mqttconnect->setText("数据库断连");
}void Widget::select_db()
{/*check_flag = 0;check_value.fill("Default", 10);  // 设置列表大小为 10,并用 "Default" 填充if(ui->checkBox_ar->isChecked()){check_value[check_flag] = ui->checkBox_ar->text();++check_flag;}if(ui->checkBox_hum->isChecked()){check_value[check_flag] = ui->checkBox_hum->text();++check_flag;}if(ui->checkBox_tem->isChecked()){check_value[check_flag] = ui->checkBox_tem->text();++check_flag;}model = new QStandardItemModel(0, 0, this);  // 0 行 0 列switch (check_flag) {case 1:model->setHorizontalHeaderLabels({check_value[0], "date"});break;case 2:model->setHorizontalHeaderLabels({check_value[0], check_value[1], "date"});break;case 3:model->setHorizontalHeaderLabels({check_value[0], check_value[1], check_value[2], "date"});break;default:model->setHorizontalHeaderLabels({check_value[0], check_value[1], check_value[2], "date"});break;}QSqlQuery query;query.exec("SELECT * FROM sensor_data");while (query.next()) {QString hum = query.value(0).toString(); // 获取第一列的值QString tem = query.value(1).toString(); // 获取第二列的值QString ar = "";QString created_at = query.value(2).toString(); // 获取第三列的值QList<QStandardItem*> row;switch(check_flag){case 1:if(check_value[0] == "hum")row << new QStandardItem(hum) << new QStandardItem(created_at);if(check_value[0] == "tem")row << new QStandardItem(tem) << new QStandardItem(created_at);if(check_value[0] == "ar")row << new QStandardItem(ar) << new QStandardItem(created_at);break;case 2:if(check_value[0] == "hum" && check_value[1] == "tem")row << new QStandardItem(hum) << new QStandardItem(tem) << new QStandardItem(created_at);if(check_value[0] == "ar" && check_value[1] == "hum")row << new QStandardItem(ar) << new QStandardItem(hum) << new QStandardItem(created_at);if(check_value[0] == "ar" && check_value[1] == "tem")row << new QStandardItem(ar) << new QStandardItem(tem) << new QStandardItem(created_at);break;case 3:row << new QStandardItem(ar) << new QStandardItem(hum) << new QStandardItem(tem) << new QStandardItem(created_at);break;default:row << new QStandardItem(ar) << new QStandardItem(hum) << new QStandardItem(tem) << new QStandardItem(created_at);break;}model->appendRow(row);  // 在末尾添加一行}ui->tableView->setModel(model);
*/if (!db.open()) {ui->textEdit_db->append("db disconnect,cannot select db");return;}ui->textEdit_db->append("test select_button");
}void Widget::close_db()
{db.close(); //关闭数据库连接以释放资源
}bool isValidIP(const QString &ip)
{QRegularExpression ipRegex("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");return ipRegex.match(ip).hasMatch();
}
bool isValidPort(int port)
{return port > 0 && port <= 65535;
}void Widget::newConnect()
{// 创建数据模型model = new QStandardItemModel(0, 0, this);  // 0 行 0 列QString ip = ui->hostLineEdit->text();if (!isValidIP(ip)) {ui->textEdit_db->append("Invalid IP address!");return;}int port = ui->portLineEdit->text().toInt();if (!isValidPort(port)) {ui->textEdit_db->append("Invalid port number!");return;}check_flag = 0;check_value.fill("Default", 10);  // 设置列表大小为 10,并用 "Default" 填充if(ui->checkBox_ar->isChecked()){check_value[check_flag] = ui->checkBox_ar->text();++check_flag;}if(ui->checkBox_hum->isChecked()){check_value[check_flag] = ui->checkBox_hum->text();++check_flag;}if(ui->checkBox_tem->isChecked()){check_value[check_flag] = ui->checkBox_tem->text();++check_flag;}switch (check_flag) {case 1:model->setHorizontalHeaderLabels({check_value[0], "created_at"});break;case 2:model->setHorizontalHeaderLabels({check_value[0], check_value[1], "created_at"});break;case 3:model->setHorizontalHeaderLabels({check_value[0], check_value[1], check_value[2], "created_at"});break;default:model->setHorizontalHeaderLabels({check_value[0], check_value[1], check_value[2], "created_at"});break;}//连接到主机,这里从界面获取主机地址和端口号tcpSocket->connectToHost(ui->hostLineEdit->text(),ui->portLineEdit->text().toInt());// 你可以检查连接状态来确定是否已成功断开,如何已经断开连接,waitForDisconnected会直接返回0if (tcpSocket->waitForDisconnected(3000)) { // 等待最多3000毫秒ui->textEdit_db->append("Disconnected successfully.");} else {ui->textEdit_db->append("Failed to disconnect within the timeout period.");}
}void Widget::readMessage()
{QDataStream in(tcpSocket);in.setVersion(QDataStream::Qt_5_14);if (tcpSocket->bytesAvailable() == 0) return;QByteArray data = tcpSocket->readAll();QString receive_data = QString::fromUtf8(data);QStringList lines = receive_data.split('\n');for(const QString &line : lines){// 跳过空行(可选)if (line.trimmed().isEmpty()) {continue;}ui->textEdit_db->setText(line);int columnCount = model->columnCount();QList<QStandardItem*> row;int i = 0;for(; i < columnCount-1; i++){QVariant columnName = model->headerData(i, Qt::Horizontal, Qt::DisplayRole);// 正则表达式用于匹配数字(整数和浮点数)QRegularExpression regex(QString(R"(%1=(\d+(?:\.\d+)?))").arg(columnName.toString()));QRegularExpressionMatchIterator j = regex.globalMatch(line);while(j.hasNext()){QRegularExpressionMatch match = j.next();QString matchedString = match.captured(1);row << new QStandardItem(matchedString);}}QVariant columnName1 = model->headerData(i, Qt::Horizontal, Qt::DisplayRole);ui->textEdit_db->append(columnName1.toString());// 正则表达式用于匹配日期QRegularExpression regex1(QString(R"(%1=(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}))").arg(columnName1.toString()));QRegularExpressionMatchIterator k = regex1.globalMatch(line);while(k.hasNext()){QRegularExpressionMatch match1 = k.next();QString matchedString1 = match1.captured(1);row << new QStandardItem(matchedString1);}model->appendRow(row);/*//2025-03-03 10:11:52QRegularExpression re("hum=(\\d+),tem=(\\d+\\.\\d+),created_at=(\\d+\\-\\d+\\-\\d+\\ \\d+\\:\\d+\\:\\d+)");QRegularExpressionMatch match = re.match(line);if(match.hasMatch()) {QString hum = match.captured(1);QString tem = match.captured(2);QString ar = "";QString created_at = match.captured(3);//QString displayMessage = QString("Humidity: %1, Temperature: %2,time: %3").arg(hum).arg(tem).arg(created_at);QList<QStandardItem*> row;switch(check_flag){case 1:if(check_value[0] == "hum")row << new QStandardItem(hum) << new QStandardItem(created_at);if(check_value[0] == "tem")row << new QStandardItem(tem) << new QStandardItem(created_at);if(check_value[0] == "ar")row << new QStandardItem(ar) << new QStandardItem(created_at);break;case 2:if(check_value[0] == "hum" && check_value[1] == "tem")row << new QStandardItem(hum) << new QStandardItem(tem) << new QStandardItem(created_at);if(check_value[0] == "ar" && check_value[1] == "hum")row << new QStandardItem(ar) << new QStandardItem(hum) << new QStandardItem(created_at);if(check_value[0] == "ar" && check_value[1] == "tem")row << new QStandardItem(ar) << new QStandardItem(tem) << new QStandardItem(created_at);break;case 3:row << new QStandardItem(ar) << new QStandardItem(hum) << new QStandardItem(tem) << new QStandardItem(created_at);break;default:row << new QStandardItem(ar) << new QStandardItem(hum) << new QStandardItem(tem) << new QStandardItem(created_at);break;}model->appendRow(row);  // 在末尾添加一行}
*/}ui->tableView->setModel(model);//tcpSocket->abort(); //立即关闭套接字,而不保证所有数据都已发送或接收。tcpSocket->disconnectFromHost();//取消已有的连接//tcpSocket->abort();
}void Widget::sendMessage()
{//用于暂存我们要发送的数据QByteArray block;//设置数据流QDataStream out(&block,QIODevice::WriteOnly);out.setVersion(QDataStream::Qt_DefaultCompiledVersion);QString message_buf;switch(check_flag){case 1:message_buf = check_value[0];break;case 2:message_buf = check_value[0]+","+check_value[1];break;case 3:message_buf = check_value[0]+","+check_value[1]+","+check_value[2];break;default://message_buf = check_flag;break;}send_data = message_buf.toUtf8();out<<static_cast<quint8>(check_flag);block.append(send_data);tcpSocket->write(block);//发送数据成功后,显示提示ui->textEdit_db->append("send message successful!!!");
}void Widget::displayError(QAbstractSocket::SocketError)
{//ui->textEdit_db->setText("error "+tcpSocket->errorString()); //输出错误信息ui->textEdit_db->append("error "+tcpSocket->errorString());
}
void Widget::pushButton_recv_clicked() //连接按钮
{newConnect(); //请求连接
}
void Widget::pushButton_del_clicked() //连接按钮
{model->clear();  // 清空模型中的数据
}
void Widget::pushButton_mqttconnect_clicked()
{if (ui->pushButton_mqttconnect->text() == "mqtt连接"){// 将QString转换为intbool ok;int value = ui->lineEdit_port->text().toInt(&ok);// 检查转换是否成功if (ok) {ui->textEdit_db->append("hostname:"+ui->lineEdit_host->text());ui->textEdit_db->append("port:"+ui->lineEdit_port->text());} else {ui->textEdit_db->append("port failed");return;}// 设置MQTT代理地址和端口mqtt_client.setHostname(ui->lineEdit_host->text()); // 公共MQTT代理mqtt_client.setPort(value); // MQTT默认端口// 连接MQTT代理mqtt_client.connectToHost();}else if (ui->pushButton_mqttconnect->text() == "mqtt断开"){ui->textEdit_db->append("pushButton_db_clicked!");mqtt_client.disconnectFromHost();ui->pushButton_mqttrecv->setEnabled(false);ui->pushButton_mqttsend->setEnabled(false);}
}
void Widget::pushButton_mqttrecv_clicked()
{// 订阅主题mqtt_client.subscribe(ui->lineEdit_recvtopic->text());ui->textEdit_db->append("recv-topic:"+ui->lineEdit_recvtopic->text());
}void Widget::pushButton_mqttsend_clicked()
{// 发布消息mqtt_client.publish(ui->lineEdit_sendtopic->text(), ui->textEdit_send->toPlainText().toUtf8());
}

UI左侧通过选择控件(checkBox)将需要的数据内容通过tcp发送到云端获取数据,并在表格控件(tableView)中展示,UI右侧通过获取host、port等对应的输入,将这些参数通过mqtt处理连接代理服务器进行发布和订阅。该代码只是实现基本功能,各位可以增加一些前置条件,比如检测输入数据的格式是否正确、检测连接是否正常。在文本控件(textEdit)中输出一些debug打印。

相关文章:

PC端QT实现mqtt客户端发布和订阅

在Windows11-64位系统下使用QT开发桌面应用程序&#xff0c;实现mqtt客户端的发布和订阅功能。 需求&#xff1a; mqtt代理服务器 --mosquitto&#xff1b; mqtt客户端工具 -- mqtt.fx&#xff1b; qtcreator开发工具 -- qtcreator6.8.2版本&#xff1b; 过程&#xff1a;…...

蓝桥云客 挖矿

0挖矿 - 蓝桥云课 问题描述 小蓝正在数轴上挖矿&#xff0c;数轴上一共有 n 个矿洞&#xff0c;第 i 个矿洞的坐标为 ai​。小蓝从 0 出发&#xff0c;每次可以向左或向右移动 1 的距离&#xff0c;当路过一个矿洞时&#xff0c;就会进行挖矿作业&#xff0c;获得 1 单位矿石&…...

React开发指南:核心、实践与案例

文章目录 一、React核心架构与设计哲学1.1 虚拟DOM与Diff算法1.2 JSX编译原理1.3 组件化设计模式1.4 Fiber架构解析1.5 组件生命周期&#xff08;类组件&#xff09; 二、React核心特性详解2.1 数据流管理2.2 Hooks革命2.3 Context API进阶2.4 自定义Hooks设计模式 三、React 1…...

落雪音乐Pro 8.8.6 | 内置8条音源,无需手动导入,纯净无广告

洛雪音乐Pro版内置多组稳定音源接口&#xff0c;省去手动导入的繁琐操作&#xff0c;安装即可畅听海量音乐。延续原版无广告的纯净体验&#xff0c;支持歌单推荐与音源切换&#xff0c;满足个性化听歌需求。此版本仅支持在线播放&#xff0c;无法下载音乐&#xff0c;且与原版不…...

Java入职篇(1)——心态篇

Java入职篇&#xff08;1&#xff09;——心态篇 本人终于通过辛苦的学习以及经过大量的面试&#xff0c;终于拿到一份offer了&#xff01;&#xff0c;但是的有点担心入职之后&#xff0c;不能胜任工作&#xff0c;不能安全度过试用期。在入职后能够顺利渡过刚开始最难熬的实…...

【后端】【django】Django DRF `@action` 详解:自定义 ViewSet 方法

Django DRF action 详解&#xff1a;自定义 ViewSet 方法 在 Django REST Framework&#xff08;DRF&#xff09;中&#xff0c;action 装饰器用于为 ViewSet 添加自定义的 API 端点。相比于 update、create 等默认方法&#xff0c;action 允许我们定义 更加清晰、语义化 的 A…...

【Vue.js】

一、简介 1、概述 官网GitHub - Vuejs Vue 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用户界面。 Vue.js作为一个渐进式框架&#xff0c;其设计理…...

SSL 和 TLS 认证

SSL&#xff08;Secure Sockets Layer&#xff0c;安全套接层&#xff09;认证是一种用于加密网络通信和验证服务器身份的安全技术。它是TLS&#xff08;Transport Layer Security&#xff0c;传输层安全协议&#xff09;的前身&#xff0c;虽然现在大多数应用使用的是TLS&…...

可复用表格组件设计与实现:分页、排序、筛选全功能解析

文章目录 一、组件设计思路1.1 功能需求分析1.2 技术选型 二、组件架构设计2.1 组件结构2.2 数据流设计 三、核心代码实现3.1 基础表格组件3.2 状态管理 四、功能模块实现4.1 分页组件4.2 排序控制4.3 筛选控制 五、性能优化方案5.1 虚拟滚动5.2 防抖筛选 六、完整测试方案6.1 …...

SmartFormat:轻量级文本模板库,轻松替代 string.Format

推荐一个 C# 编写的轻量级文本模板库&#xff0c;可以作为 string.Format 的替代品。 01 项目简介 SmartFormat不仅继承了 string.Format 的功能&#xff0c;还扩展了更多高级特性&#xff0c;例如命名占位符、列表格式化、本地化支持、复数化等。SmartFormat 提供了高性能、…...

【贪心算法4】

力扣452.用最少数量的剪引爆气球 链接: link 思路 这道题的第一想法就是如果气球重叠得越多那么用箭越少&#xff0c;所以先将气球按照开始坐标从小到大排序&#xff0c;遇到有重叠的气球&#xff0c;在重叠区域右边界最小值之前的区域一定需要一支箭&#xff0c;这道题有两…...

ES 使用geo point 查询离目标地址最近的数据

需求描述&#xff1a;项目中需要通过经纬度坐标查询目标地所在的行政区。 解决思路大致有种&#xff0c;使用es和mysql分别查询。 1、使用es进行查询 将带有经纬度坐标的省市区数据存入es中&#xff0c;mappings字段使用geo point类型&#xff0c;索引及查询dsl如下。 geo p…...

CentOS7 服务器安装 Hadoop 和 Hive

CentOS 服务器安装 Hadoop 和 Hive流程 请将以下的路径更换为自己的路径 1. 环境准备 1.1 安装 JDK Hadoop 和 Hive 需要 Java 运行环境&#xff0c;这里安装 OpenJDK 1.8&#xff1a; # 查看 Java 版本 java -version1.2 创建 Hadoop 用户&#xff08;可选&#xff09; …...

C语言零基础入门:嵌入式系统开发之旅

C语言零基础入门&#xff1a;嵌入式系统开发之旅 一、引言 嵌入式系统开发是当今科技领域中一个极具魅力和挑战性的方向。从智能家居设备到汽车电子系统&#xff0c;从智能穿戴设备到工业自动化控制&#xff0c;嵌入式系统无处不在。而C语言&#xff0c;作为嵌入式开发中最常…...

【数据分享】1999—2023年地级市地方一般公共预算收支状况数据(科学技术支出/教育支出等)

在之前的文章中&#xff0c;我们分享过基于2000-2024年《中国城市统计年鉴》整理的1999-2023年地级市的人口相关数据、染物排放和环境治理相关数据、房地产投资情况和商品房销售面积相关指标数据和社会消费品零售总额和年末金融机构存贷款余额&#xff08;均可查看之前的文章获…...

直方图(信息学奥赛一本通-1115)

【题目描述】 给定一个非负整数数组&#xff0c;统计里面每一个数的出现次数。我们只统计到数组里最大的数。假设 Fmax&#xff08;Fmax<10000&#xff09;是数组里最大的数&#xff0c;那么我们只统计{0,1,2.....Fmax}里每个数出现的次数。 【输入】 第一行n是数组的大小。…...

基于NXP+FPGA轨道交通人机交互(HMI)和健康管理单元(PHM)解决方案

人机接口 (HMI) 是交互式显示设备&#xff0c;可用于司机和乘务员的交互式信息显示。也可以用于CCTV监视。满足多种接口设备连接的同时&#xff0c;搭载的Linux系统&#xff0c;可以满足客户的定制化需求。 关键特性 触摸式按键位于显示区域周围&#xff0c;耐用性好&#xff0…...

宇树与智元的崛起:机器人“灵魂”注入的技术密码

目录 机器人运动的基石&#xff1a;大扭矩与平衡术 大扭矩&#xff1a;力量的源泉 平衡术&#xff1a;动态平衡的艺术 从运动到智能&#xff1a;AI学习的“灵魂”注入 强化学习&#xff1a;试错中的成长 模仿学习&#xff1a;站在巨人的肩膀上 数据与知识共享&#xff1…...

TCP 全连接队列 内核层理解socket

TCP 全连接队列 理解 listen 的第二个参数 int listen(int sockfd, int backlog);backlog 参数表示 全连接队列&#xff08;accept 队列&#xff09;的最大长度。 那什么是全连接队列呢&#xff1f; 三次握手 & accept() 处理流程 客户端发送 SYN&#xff0c;服务器收到并…...

成功破解加密机制,研究人员解锁LinuxESXi Akira勒索软件

一位网络安全研究人员成功破解了Akira勒索软件在Linux/ESXi系统中的加密机制&#xff0c;使得受害者无需支付赎金即可恢复数据。 这一突破利用了勒索软件加密方法中的关键漏洞。据研究人员介绍&#xff0c;该恶意软件使用纳秒级的时间戳作为加密过程中的种子&#xff0c;这使其…...

vue2:el-table列中文字前面加icon图标的两种方式

1、文字前面加icon <el-table-column label="姓名" align="left" prop="nickName"><template #default="{ row }"><i v-if="row.sync" class="el-icon-lock"></i><span>{{ row.nic…...

深入探索Android Bitmap:从原理到实战

一、Bitmap 是什么 在 Android 开发中&#xff0c;Bitmap 是极为重要的基石。简单来说&#xff0c;Bitmap 代表位图&#xff0c;是图片在内存里的具体呈现形式 &#xff0c;任何诸如 JPEG、PNG、WEBP 等格式的图片&#xff0c;一旦被加载到内存中&#xff0c;就会以 Bitmap 对…...

软考计算机知识-流水线

计算机流水线类似工业生产过程的流水线&#xff0c;在同一时间&#xff0c;m个部件进行不同的操作&#xff0c;完成对不同对象的处理。 理解重叠&#xff1a;让不同的指令在时间上重叠地解释。在解释第k条指令的操作完成之前&#xff0c;就可以开始解释第k1条指令。 题1&#…...

【Linux】从互斥原理到C++ RAII封装实践

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…...

【哈希表与字符串的算法之路:思路与实现】—— LeetCode

文章目录 两数之和面试题01.02.判定是否为字符重排存在重复元素存在重复元素||字母异位词分组最长公共前缀和最长回文子串二进制求和字符串相乘 两数之和 这题的思路很简单&#xff0c;在读完题目之后&#xff0c;便可以想到暴力枚举&#xff0c;直接遍历整个数组两遍即可&…...

rdiff-backup备份

目录 1. 服务器备份知识点 1.1 备份策略 1.2 备份步骤和宝塔面板简介 1.3 CentOS7重要目录 2. 备份工具 2.1 tar -g 备份演示 2. rsync 备份演示 3. rdiff-backup 备份演示 4. 差异和优缺点 3. rdiff-backup安装和使用 3.1 备份命令rdiff-backup 3.2 恢复命令--…...

Netty基础—4.NIO的使用简介一

大纲 1.Buffer缓冲区 2.Channel通道 3.BIO编程 4.伪异步IO编程 5.改造程序以支持长连接 6.NIO三大核心组件 7.NIO服务端的创建流程 8.NIO客户端的创建流程 9.NIO优点总结 10.NIO问题总结 1.Buffer缓冲区 (1)Buffer缓冲区的作用 (2)Buffer缓冲区的4个核心概念 (3)使…...

贪心算法简介(greed)

前言&#xff1a; 贪心算法&#xff08;Greedy Algorithm&#xff09;是一种在每个决策阶段都选择当前最优解的算法策略&#xff0c;通过局部最优的累积来寻求全局最优解。其本质是"短视"策略&#xff0c;不回溯已做选择。 什么是贪心、如何来理解贪心(个人对贪心的…...

驻场运维服务方案书(Word文件)

目 录 第一章 背景分析 1.1. 项目背景 1.2. 项目目标 1.3. 系统现状 1.3.1. 网络系统 1.3.2. 设备清单梳理 1.3.3. 应用系统 第二章 需求分析及理解 2.1. 在重要日期能保障信息系统安全 2.2. 信息系统可长期安全、持续、稳定的运行 2.3. 提升发现安全问题、解决安全…...

嵌入式硬件--开发工具-AD使用常用操作

ad16.1.12 1.如何显示/隐藏其他图层 在pcb界面点击L--试图界面中找到“视图选项”--单层模式选择 not in single layer mode 在pcb界面点击L--试图界面中找到“视图选项”--单层模式选择 gray scale other layers 【Altium】AD如何只显示一层&#xff0c;隐藏其他层显示&…...

在 Ubuntu 上安装和配置 Docker 的完整指南

Docker 是一个开源的平台&#xff0c;旨在简化应用程序的开发、部署和运行。通过将应用程序及其依赖项打包到容器中&#xff0c;Docker 确保应用程序可以在任何环境中一致地运行。 目录 前言安装前的准备安装 Docker 步骤 1&#xff1a;更新包索引步骤 2&#xff1a;安装必要…...

微服务全局ID方案汇总

自增id 对于大多数系统来说&#xff0c;使用mysql的自增id当作主键再最合适不过了。在数据库层面就可以获取一个顺序的、唯一的、空间占用少的id。 自增id需要是 int、bigint这些整数类型&#xff0c;uint 支持 40 亿的数据量&#xff0c;bigint unsign&#xff08;0 &#x…...

实验5 逻辑回归

实验5 逻辑回归 【实验目的】掌握逻辑回归算法 【实验内容】处理样本&#xff0c;使用逻辑回归算法进行参数估计&#xff0c;并画出分类边界 【实验要求】写明实验步骤&#xff0c;必要时补充截图 1、参照“2.1梯度下降法实现线性逻辑回归.ipynb”和“2.2 sklearn实现线性逻辑…...

【原创】在高性能服务器上,使用受限用户运行Nginx,充当反向代理服务器[未完待续]

1 起因 在公共高性能服务器上运行OllamaDeepSeek&#xff0c;如果按照默认配置启动Ollama程序&#xff0c;则自己在远程无法连接你启动的Ollama服务。 如果修改掉默认的配置&#xff0c;则会遇到你的Ollama被他人完全控制的安全风险。 不过&#xff0c;我们可以使用一个方向…...

Linux 下 MySQL 8 搭建教程

一、下载 你可以从 MySQL 官方下载地址 下载所需的 MySQL 安装包。 二、环境准备 1. 查看 MySQL 是否存在 使用以下命令查看系统中是否已经安装了 MySQL&#xff1a; rpm -qa|grep -i mysql2. 清空 /etc/ 目录下的 my.cnf 执行以下命令删除 my.cnf 文件&#xff1a; [roo…...

vue 仿deepseek前端开发一个对话界面

后端&#xff1a;调用deepseek的api&#xff0c;所以返回数据格式和deepseek相同 {"model": "DeepSeek-R1-Distill-Qwen-1.5B", "choices": [{"index": 0, "delta": {"role": "assistant", "cont…...

MinIO问题总结(持续更新)

目录 Q: 之前使用正常&#xff0c;突然使用空间为0B&#xff0c;上传文件也是0B&#xff08;部署在k8s中&#xff09;Q: 无法上传大文件参考yaml Q: 之前使用正常&#xff0c;突然使用空间为0B&#xff0c;上传文件也是0B&#xff08;部署在k8s中&#xff09; A: 1、检查pod状态…...

STM32配套程序接线图

1 工程模板 2 LED闪烁 3LED流水灯 4蜂鸣器 5按键控制LED 6光敏传感器控制蜂鸣器 7OLED显示屏 8对射式红外传感器计次 9旋转编码器计次 10 定时器定时中断 11定时器外部时钟 12PWM驱动LED呼吸灯 13 PWM驱动舵机 14 PWM驱动直流电机 15输入捕获模式测频率 16PWMI模式测频率占空…...

深入理解Linux网络随笔(七):容器网络虚拟化--Veth设备对

深入理解Linux网络随笔&#xff08;七&#xff09;&#xff1a;容器网络虚拟化 微服务架构中服务被拆分成多个独立的容器&#xff0c;docker网络虚拟化的核心技术为&#xff1a;Veth设备对、Network Namespace、Bridg。 Veth设备对 veth设备是一种 成对 出现的虚拟网络接口&…...

实战指南:鸿蒙ArkTS中实现列表下拉刷新与触底加载的完整解析

前言&#xff1a; 在移动应用开发中&#xff0c;下拉刷新和触底加载更多是提升用户体验的核心功能。鸿蒙ArkUI框架通过Refresh组件和List组件的onReachEnd事件&#xff0c;为开发者提供了简洁高效的实现方案。本文将通过代码示例&#xff0c;详解如何利用ArkTS实现这两个功能。…...

【栈数据结构应用解析:常见算法题详细解答】—— Leetcode

文章目录 栈的模拟实现删除字符串中的所有相邻重复项比较含退格的字符串基本计算器||字符串解码验证栈序列 栈的模拟实现 #include <iostream>using namespace std;const int N 1e5 10;// 创建栈 int stk[N], n;// 进栈 - 本质就是顺序表里面的尾插 void push(int x) …...

Git常用操作之GitLab

Git常用操作之GitLab 小薛博客官网&#xff1a;小薛博客Git常用操作之GitLab官方地址 1、GitLab安装 https://gitlab.cn/install/ 1、Docker安装GitLab https://docs.gitlab.cn/jh/install/docker.html 1、设置卷位置 在设置其他所有内容之前&#xff0c;请配置一个新的…...

2025探索短剧行业新可能报告40+份汇总解读|附PDF下载

原文链接&#xff1a;https://tecdat.cn/?p41043 近年来&#xff0c;短剧以其紧凑的剧情、碎片化的观看体验&#xff0c;迅速吸引了大量用户。百度作为互联网巨头&#xff0c;在短剧领域积极布局。从早期建立行业专属模型冷启动&#xff0c;到如今构建完整的商业生态&#xf…...

各省水资源平台 水资源遥测终端机都用什么协议

各个省水资源平台 水资源遥测终端机 的建设大部分从2012年开始启动&#xff0c;经过多年建设&#xff0c;基本都已经形成了稳定的通讯要求&#xff1b;河北瑾航科技 遥测终端机&#xff0c;兼容了大部分省市的通讯协议&#xff0c;如果需要&#xff0c;可以咨询和互相学习&…...

C#+EF+SqlServer性能优化笔记

文章目录 前言一、C#EF 代码优化1.接口代码改异步2.查询异步&#xff0c;只查询需要的数据3.查询数据判断时4.直接使用sql查询 二、数据库优化1.减少关联表&#xff0c;一些基础数据&#xff0c;字典表可以考虑放到redis中&#xff0c;在代码中映射2.增加索引&#xff0c;删除无…...

列表动态列处理

1、在initialize()方法里&#xff0c;获取列表控件&#xff0c;添加CreateListColumnsListener监听 public void initialize(){ BillList billlist(BillList)this.getControl("billlistap"); billlist.addCreateListColumnsListener(this::beforeCreateListColumns)…...

电机控制常见面试问题(十二)

文章目录 一.电机锁相环1.理解锁相环2.电机控制中的锁相环应用3.数字锁相环&#xff08;DPLL&#xff09; vs 模拟锁相环&#xff08;APLL&#xff09;4.锁相环设计的关键技术挑战5.总结 二、磁链观测1.什么是磁链&#xff1f;2.为什么要观测磁链&#xff1f;3.怎么观测磁链&am…...

芯驿电子 ALINX 亮相德国纽伦堡,Embedded World 2025 精彩回顾

2025年3月13日&#xff0c;全球规模最大的嵌入式行业盛会——德国纽伦堡国际嵌入式展&#xff08;embedded world 2025&#xff09;圆满落幕。 在这场汇聚全球 950 家展商、3 万余专业观众的科技盛宴中&#xff0c;芯驿电子 ALINX 展位人头攒动&#xff0c;多款尖端产品吸引客户…...

西门子S7-1200 PLC远程上下载程序方案

西门子S7-1200 PLC远程上下载程序方案&#xff08;巨控GRM552YW-C模块&#xff09; 三步完成配置 | 全球适用 | 稳定高效 三步快速完成远程配置 硬件部署 准备巨控GRM552YW-CHE模块1台&#xff0c;通过网口连接西门子S7-1200 PLC以太网口。 模块支持4G/5G/Wi-Fi/网线接入外网…...

MFC窗口的创建/消息映射机制

mfc.h #include<afxwin.h>//mfc头文件//应用程序类 class MyApp:public CWinApp //继承于应用程序类 { public://程序入口virtual BOOL InitInstance(); };//框架类 class MyFrame:public CFrameWnd { public:MyFrame();//声明宏 提供消息映射机制DECLARE_MESSAGE_MAP()…...