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

MQTT 协议详解:物联网通信的利器

在当今物联网(IoT)迅猛发展的背景下,设备之间的高效、可靠通信变得尤为重要。MQTT(Message Queuing Telemetry Transport)作为一种轻量级的消息传输协议,因其低带宽占用和高可靠性,成为物联网领域中广受欢迎的通信工具。

官网:http://mqtt.org

1. 什么是 MQTT?

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)是一种基于发布/订阅(publish/subscribe)模型的轻量级通信协议,专为资源受限的设备和不可靠网络环境设计。它最初由 Andy Stanford-Clark 和 Arlen Nipper 在 1999 年开发,如今已成为物联网通信的标准协议之一。
MQTT 的核心思想是通过一个中间代理(Broker)来实现消息的分发,从而解耦发送者与接收者。

客户端

服务端

一个使用MQTT协议的应用程序或者设备,它总是建立到服务器的网络连接。客户端可以:

也称为"消息代理"(Broker),可以是一个应用程序或一台设备。它是位于消息发布者和订阅者之间,它可以:

- (1)发布其他客户端可能会订阅的信息;

- (1)接受来自客户的网络连接;

- (2)订阅其它客户端发布的消息;

- (2)接受客户发布的应用信息;

- (3)退订或删除应用程序的消息;

- (3)处理来自客户端的订阅和退订请求;

- (4)断开与服务器连接。

- (4)向订阅的客户转发应用程序消息。

 2. 设计原则

  1. 精简,不添加可有可无的功能;
  2. 发布/订阅(Pub/Sub)模式,方便消息在传感器之间传递,解耦Client/Server模式,带来的好处在于不必预先知道对方的存在(ip/port),不必同时运行;
  3. 允许用户动态创建主题(不需要预先创建主题),零运维成本;
  4. 把传输量降到最低以提高传输效率;
  5. 把低带宽、高延迟、不稳定的网络等因素考虑在内;
  6. 支持连续的会话保持和控制(心跳);
  7. 理解客户端计算能力可能很低;
  8. 提供服务质量( quality of service level:QoS)管理;
  9. 不强求传输数据的类型与格式,保持灵活性(指的是应用层业务数据)。

3. MQTT 核心概念

3.1 服务端(Broker)

消息的中转站,负责接收来自客户端的消息,并将消息转发给订阅了相关主题的客户端。

3.2 客户端(Client)

客户端可以是发布者(Publisher)或订阅者(Subscriber),也可以两者兼有。每个客户端都可以连接到 Broker 并进行消息的发布或订阅。

3.3 主题(Topic)

类似于邮件地址的主题字符串,用于标识消息的分类。例如:

  • sensor/temperature
  • home/livingroom/light

3.4 Topic 通配符匹配规则

3.4.1 层级分隔符:/

/ 用来分隔主题树的每一层,并给主题空间提供分等级的结构。当两个通配符在一个主题中出现的时候,主题层次分隔符的使用是很重要的。

示例:
love/you/with/all/my/heart

3.4.2  多层通配符:#

多层通配符有可以标识大于等于0的层次。因此,love/# 也可以匹配到单独的 love,此时#代表0层。

多层通配符一定要是主题树的最后一个字符。比如说,love/# 是有效的,但是 love/#/with 是无效的。

love/you/# 可匹配如下内容(包括单不限于):love/you
love/you/with
love/you/with/all
love/you/with/all/my/heart
love/you/with/all/my/hearts

 3.4.3 单层通配符:+

只匹配主题的一层

1. love/you/+ :匹配/love/you/with和/love/you/and,但是不匹配love/you/with/all/my/heart。
2. 单层通配符只匹配1层,love/+不匹配love。
3. 单层通配符可以被用于主题树的任意层级,连带多层通配符。它必须被用在主题层级分隔符/的右边,除非它是指定自己。因此,+和love/+都是有效的,但是love+无效。单层通配符可以用在主题树的末端,也可以用在中间。比如说,love/+和love/+/with都是有效。

注意事项:

  1. 主题层次分隔符被用来在主题中引入层次。多层的通配符和单层通配符可以被使用,但他们不能被使用来做发布者的消息。
  2. Topic命名尽量见名知意,符合规范,主题名字是大小写敏感的。比如说,love和LOVE是两个不同的主题。
  3. 以/开头会产生一个不同的主题。比如说,/love与love不同。/love匹配"+/+"和/+,但不匹配+。
  4. 不要在任何主题中包含null(Unicode \x0000)字符。
  5. 在主题树中,长度被限制于64k内但是在这以内没有限制层级的数目。
  6. 可以有任意数目的根节点: 也就是说,可以有任意数目的主题树。 

3.5 $SYS 主题

以 $SYS/ 开头的主题为系统主题,系统主题主要用于获取 MQTT 服务器自身运行状态、消息统计、客户端上下线事件等数据。目前,MQTT 协议暂未明确规定 $SYS/ 主题标准,但大多数 MQTT 服务器都遵循该标准建议。

例如,EMQX 服务器支持通过以下主题获取集群状态。

主题说明
$SYS/brokersEMQX 集群节点列表
$SYS/brokers/emqx@127.0.0.1/versionEMQX 版本
$SYS/brokers/emqx@127.0.0.1/uptimeEMQX 运行时间
$SYS/brokers/emqx@127.0.0.1/datetimeEMQX 系统时间
$SYS/brokers/emqx@127.0.0.1/sysdescrEMQX 系统信息

EMQX 还支持客户端上下线事件、收发流量、消息收发、系统监控等丰富的系统主题,用户可通过订阅 $SYS/# 主题获取所有系统主题消息。详细请见:EMQX 系统主题文档。 

3.6 QoS(服务质量等级)

MQTT 协议中规定了消息服务质量(Quality of Service),它保证了在不同的网络环境下消息传递的可靠性,QoS 的设计是 MQTT 协议里的重点。
MQTT 设计了 3 个 QoS 等级。

3.6.1 QoS 0(最多一次)

消息发布完全依赖底层TCP/IP网络。会发生消息丢失。 一个消息不会被接收端应答,也不会被发送者存储并再发送。这个也被叫做“即发即弃”

3.6.2 QoS 1(至少一次)

确保消息到达,但消息重复可能会发生。发送者将会存储发送的信息直到发送者收到一次来自接收者的PUBACK格式的应答。

3.6.3 QoS 2(恰好一次)

确保消息到达一次。如果接收端接收到了一个QoS为2的PUBLISH消息,它将相应地处理PUBLISH消息,并通过PUBREC消息向发送方确认。

其中:

  • PUBLISH:发布消息 
  • PUBREC:发布收到
  • PUBREL:发布释放
  • PUBCOMP:发布完成

3.6.4 QoS 匹配规则总结

 不同情况下,客户端收到的消息 QoS 可参考下表:

发布消息的 QoS

主题订阅的 QoS

接收消息的 QoS

0

0

0

0

1

0

0

2

0

1

0

0

1

1

1

1

2

1

2

0

0

2

1

1

2

2

2

MQTT 中的 QoS 是一种灵活的机制,它允许发布者和订阅者独立设置期望的服务质量等级,而最终的消息传输将基于两者之间的最小值进行处理。这种设计既保障了通信的可靠性,也避免了因能力不匹配导致的资源浪费。

3.7 MQTT V3.1.1 协议报文

3.7.1 报文结构

  • 固定报头(Fixed header)
  • 可变报头(Variable header)
  • 报文有效载荷(Payload)

3.7.2 固定报头

+----------+-----+-----+-----+-----+-----+-----+-----+-----+
| Bit      |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
+----------+-----+-----+-----+-----+-----+-----+-----+-----+
| byte1    |   MQTT Packet type    |         Flags         |
+----------+-----------------------+-----------------------+
| byte2... |   Remaining Length                            |
+----------+-----------------------------------------------+

3.7.3 报文类型

类型名称类型值报文说明
CONNECT1发起连接
CONNACK2连接回执
PUBLISH3发布消息
PUBACK4发布回执
PUBREC5QoS2 消息回执
PUBREL6QoS2 消息释放
PUBCOMP7QoS2 消息完成
SUBSCRIBE8订阅主题
SUBACK9订阅回执
UNSUBSCRIBE10取消订阅
UNSUBACK11取消订阅回执
PINGREQ12PING 请求
PINGRESP13PING 响应
DISCONNECT14断开连接

其中:

  • PUBLISH 发布消息:PUBLISH 报文承载客户端与服务器间双向的发布消息。 PUBACK 报文用于接收端确认 QoS1 报文,PUBREC/PUBREL/PUBCOMP 报文用于 QoS2 消息流程。
  • PINGREQ/PINGRESP 心跳:客户端在无报文发送时,按保活周期(KeepAlive)定时向服务端发送 PINGREQ 心跳报文,服务端响应 PINGRESP 报文。PINGREQ/PINGRESP 报文均 2 个字节。

3.8 MQTT WebSocket 连接

MQTT 协议除支持 TCP 传输层外,还支持 WebSocket 作为传输层。通过 WebSocket 浏览器可以直连 MQTT 消息服务器,发布订阅模式与其他 MQTT 客户端通信。

MQTT 协议的 WebSocket 连接,必须采用 binary 模式,并携带子协议 Header:

Sec-WebSocket-Protocol: mqttv3.1 或 mqttv3.1.1

4. 物联网级消息中间件EMQ

4.1 EMQX 简介

EMQ X Broker 是基于高并发的 Erlang/OTP 语言平台开发,支持百万级连接和分布式集群架构,发布订阅模式的开源 MQTT 消息服务器。

EMQ官网:EMQ: 连接物理世界与人工智能

 EMQX 文档:产品概览 | EMQX 1.0 文档

为什么选择EMQ X ?从支持 MQTT5.0、稳定性、扩展性、集群能力等方面考虑,EMQX 的表现应该是最好的。

4.2 EMQX的特点

  • EMQ X 目前为开源社区中最流行的 MQTT 消息中间件;
  • EMQ X 是开源社区中第一个支持 5.0协议规范的消息服务器,并且完全兼容 MQTT V3.1 和 V3.1.1 协议。
  • 除了 MQTT 协议之外,EMQ X 还支持MQTT-SN、CoAP、 LwM2M、LoRaWAN 和 WebSocket 等物联网协议
  • 单机支持百万连接,集群支持千万级连接;毫秒级消息转发。
  • 易于安装和使用;
  • 中国本地的技术支持服务;
  • 扩展模块和插件,EMQ X 提供了灵活的扩展机制,支持企业的一些定制场景;
  • 桥接
  • 共享订阅

 4.3 环境搭建与配置

以 Docker 运行单个 EMQX 节点为例:

1. 拉取emqx镜像

docker pull emqx/emqx:v4.1.0

2. 创建emqx容器

docker run -tid --name emqx -p 1883:1883 -p 8083:8083 -p 8883:8883 -p 8084:8084 -p 18083:18083  emqx/emqx:v4.1.0

其中,端口说明:

端口协议描述
1883TCPMQTT over TCP 监听器端口,主要用于未加密的 MQTT 连接。
8883TCPMQTT over SSL/TLS 监听器端口,用于加密的 MQTT 连接。
8083TCPMQTT over WebSocket 监听器端口,使 MQTT 能通过 WebSocket 进行通信。
8084TCPMQTT over WSS (WebSocket over SSL) 监听器端口,提供加密的 WebSocket 连接。
18083HTTPEMQX Dashboard 和 REST API 端口,用于管理控制台和 API 接口。
4370TCPErlang 分布式传输端口,根据节点名称不同实际端口可能是 BasePort (4370) + Offset
5370TCP集群 RPC 端口(在 Docker 环境下为 5369),根据节点名称不同实际端口可能是 BasePort (5370) + Offset

Docker 部署注意事项:

 1. 如果需要持久化 Docker 容器中生成的数据 ,请将以下目录挂载到容器外部,这样即使容器被删除数据也不会丢失:

/opt/emqx/data
/opt/emqx/log

启动容器并挂载目录:

docker run -tid --name emqx \-p 1883:1883 -p 8083:8083 \-p 8084:8084 -p 8883:8883 \-p 18083:18083 \-v $PWD/data:/opt/emqx/data \-v $PWD/log:/opt/emqx/log \emqx/emqx:v4.1.0

EMQX 历史版本:Directory listing for EMQX: / | EMQ

单节点部署:安装部署和迁移 | EMQX文档 

集群部署:分布式集群介绍 | EMQX文档

安全认证:安全指南 | EMQX文档

EMQX命令行:命令行 | EMQX文档

配置文件:配置文件简介 | EMQX文档

4.4 EMQX 目录结构

目录描述压缩包解压安装(同 Docker)二进制包安装
etc静态配置文件./etc/etc/emqx
data数据和配置文件./data/var/lib/emqx
log日志文件./log/var/log/emqx
releases启动相关的脚本./releases/usr/lib/emqx/releases
bin可执行文件./bin/usr/lib/emqx/bin
libErlang 代码./lib/usr/lib/emqx/lib
erts-*Erlang 虚拟机文件./erts-*/usr/lib/emqx/erts-*
plugins插件./plugins/usr/lib/emqx/plugins

以上目录中,用户经常接触与使用的是 bin、etc、data、log 目录。

4.5 EMQ Dashboard

EMQ X 提供了 Dashboard 以方便用户管理设备与监控相关指标。通过 Dashboard可以查看服务器基本信息、负载情况和统计数据,可以查看某个客户端的连接状态等信息甚至断开其连接,也可以动态加载和卸载指定插件。

访问地址:http://localhost:18083 来查看 Dashboard,默认用户名是 admin,密码是 public。

EMQX Dashboard 详细介绍:EMQX Dashboard | EMQX文档

EMQX Dashboard 之 MQTT 配置:配置和管理会话持久化 | EMQX文档

导航项目

说明

Monitor

提供了服务端与客户端监控信息的展示页面

RULE ENGINE

提供了规则引擎的可视化操作页面

MANAGEMENT

提供了扩展插件与应用的管理页面

TOOLS

提供了 Websocket 客户端工具以及 HTTP API 速查页面

ADMIN

提供了 Dashboard 用户管理和显示设置等页面

4.6 客户端调试工具MQTTX

MQTT X 是 EMQ 开源的一款优雅的跨平台 MQTT 5.0 桌面客户端,它支持 macOS, Linux, Windows。

MQTT X 的 UI 采用了聊天界面形式,简化了页面操作逻辑,用户可以快速创建连接,允许保存多个客户端,方便用户快速测试 MQTT/MQTTS 连接,及 MQTT 消息的订阅和发布。

 下载地址:MQTTX:全功能 MQTT 客户端工具

4.7 基础使用教程

1. 点击 + ,再点击 New Connetion

2. 填写信息并点击右上角的 Connect ,如果无其他需求,仅填写第一页内容即可,其他均为拓展项。

 

 3. 点击 Connect 即可正常使用

 界面说明:

4. 发送消息:

 5. 订阅消息:

 

 关于切换中文:

4.8 共享订阅

对应文档:共享订阅 | EMQX文档

EMQX 实现了 MQTT 的共享订阅功能。共享订阅是一种订阅模式,用于在多个订阅者之间实现负载均衡。客户端可以分为多个订阅组,消息仍然会被转发到所有订阅组,但每个订阅组内只有一个客户端接收消息。您可以为一组订阅者的原始主题添加前缀以启用共享订阅。EMQX 支持两种格式的共享订阅前缀,分别为带群组的共享订阅(前缀为 $share/<group-name>/)和不带群组的共享订阅(前缀为 $queue/)。两种共享订阅格式示例如下:

前缀格式示例前缀真实主题名
带群组格式$share/abc/t/1$share/abc/t/1
不带群组格式$queue/t/1$queue/t/1

 需要在EMQDashboard开启该选项:(默认开启)

4.7.1 不带群组的共享订阅

格式:$queue/{TopicName}

EMQX 的共享订阅支持和策略配置:/etc/emqx.conf

# 均衡策略
## Dispatch strategy for shared subscription
##
## Value: Enum
## - random
## - round_robin
## - sticky
## - hash
broker.shared_subscription_strategy=random

均衡策略

描述

random

在所有订阅者中随机选择

round_robin

按照订阅顺序轮询

sticky

一直发往上次选取的订阅者

hash

按照发布者 ClientID 的哈希值

调用示例:

 

 

4.7.2 带群组的共享订阅

格式:$share/<group-name>/{TopicName}

 调用示例:

 

 

 

4.8 保留消息(Retained Message)

Broker 可以保留某个主题的最后一条消息,当新客户端订阅该主题时,会立即收到这条保留消息。

需要在EMQDashboard开启该选项:(默认开启)

配置示例:

发送消息时勾选 Retain 选项。

4.9 遗嘱消息(Last Will and Testament, LWT)

客户端可以在连接时设置一个“遗嘱”,如果客户端异常断开连接,Broker 将自动发布该遗嘱消息。

配置示例:

1. 在连接配置时,将页面下拉,在 Last Will and Testament 部分,填写遗嘱消息的配置。

  • 遗嘱消息主题:输入 offline
  • 遗嘱消息 QoS:保持默认值 0
  • 遗嘱消息保留标志:默认禁用。如果启用,遗嘱消息也将是一个保留消息。
  • 遗嘱消息:输入 I'm offline
  • 遗嘱消息延迟时间:设置为 5 秒。

 4.10 排他订阅

排它订阅是 EMQX 支持的 MQTT 扩展功能。排它订阅允许对主题进行互斥订阅,一个主题同一时刻仅被允许存在一个订阅者,在当前订阅者未取消订阅前,其他订阅者都将无法订阅对应主题。

要进行排它订阅,您需要为主题名称添加前缀,如以下表格中的示例:

示例前缀真实主题名
$exclusive/t/1$exclusive/t/1

 当某个客户端 A 订阅 $exclusive/t/1 后,其他客户端再订阅 $exclusive/t/1 时都会失败,直到 A 取消了对 $exclusive/t/1 的订阅为止。

注意:

排它订阅必须使用 $exclusive/ 前缀,在上面的示例中,其他客户端依然可以通过 t/1 成功进行订阅。

4.10.1 订阅失败错误码​

错误码原因
0x8F使用了 $exclusive/,但并未开启排它订阅
0x97已经有客户端订阅了该主题

 4.10.2 配置排它订阅

1. 开启排他订阅(默认不支持)

方式一:通过配置文件配置排它订阅

mqtt.exclusive_subscription.enable = true

方式二:通过界面配置 

 2. 填写 $exclusive/ + 真实主题名

 4.11 延迟发布

EMQ X 的延迟发布功能可以实现按照用户配置的时间间隔延迟发布 PUBLISH 报文的功能。模块开启emqx_mod_delayed

通过 Dashboard 配置延迟发布:(默认关闭)

延迟发布主题的具体格式如下:

$delayed/{DelayInterval}/{TopicName}

其中: 

  • $delayed: 使用 $delayed 作为主题前缀的消息都将被视为需要延迟发布的消息。
  • {DelayInterval}: 指定该 MQTT 消息延迟发布的时间间隔,单位是秒,允许的最大间隔是 4294967 秒。
  • {TopicName}: MQTT 消息的主题名称。 

发送示例:

5. Eclipse Paho

5.1 Eclipse Paho是什么

Eclipse paho 是 EMQX 官方推荐的实现了 mqtt 协议 Java 客户端。

其关系类似于 Mysql 于 JDBC ,我们的项目代码要连接数据库需要用到 JDBC ,而我们的项目需要连接 EMQX 需要用到 Eclipse Paho ,并且它提供了基础的消息收发。

5.2 Eclipse Paho技术调研

全语言编程:MQTT 客户端编程 | EMQX文档

Java 编程:如何在 Java 中使用 Paho MQTT 客户端 | EMQ

1. 添加依赖

<dependency><groupId>org.eclipse.paho</groupId><artifactId>org.eclipse.paho.client.mqttv3</artifactId><version>1.2.5</version>
</dependency>

2. 发布消息到EMQ

import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttClientPersistence;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.web.bind.annotation.GetMapping;@GetMapping("/publish")
public void publish() throws MqttException {MqttClientPersistence persistence = new MemoryPersistence();//内存持久化MqttClient client = new MqttClient("tcp://localhost:1883", "random123", persistence);//连接选项中定义用户名密码和其它配置MqttConnectOptions options = new MqttConnectOptions();options.setCleanSession(true);//参数为true表示清除缓存,也就是非持久化订阅者,这个时候只要参数设为true,一定是非持久化订阅者。而参数设为false时,表示服务器保留客户端的连接记录options.setAutomaticReconnect(true);//是否自动重连options.setConnectionTimeout(30);//连接超时时间  秒options.setKeepAliveInterval(10);//连接保持检查周期  秒options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1); //版本client.connect(options);//连接client.publish("topic", "发送内容".getBytes(), 2, false);}

3. 订阅消息

import org.eclipse.paho.client.mqttv3.*;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.web.bind.annotation.GetMapping;@GetMapping("/subscribe")public void subscribe() throws MqttException {MqttClientPersistence persistence = new MemoryPersistence();//内存持久化MqttClient client = new MqttClient("tcp://192.168.200.128:1883", "random456", persistence);//连接选项中定义用户名密码和其它配置MqttConnectOptions options = new MqttConnectOptions();options.setCleanSession(true);//参数为true表示清除缓存,也就是非持久化订阅者,这个时候只要参数设为true,一定是非持久化订阅者。而参数设为false时,表示服务器保留客户端的连接记录options.setAutomaticReconnect(true);//是否自动重连options.setConnectionTimeout(30);//连接超时时间  秒options.setKeepAliveInterval(10);//连接保持检查周期  秒options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1); //版本// 获取全部主题的消息client.setCallback(new MqttCallbackExtended() {@Overridepublic void connectionLost(Throwable throwable) {System.out.println("连接丢失!");}@Overridepublic void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {System.out.println("接收到消息  topic:" + topic + "  id:" + mqttMessage.getId() + " message:" + mqttMessage.toString());}@Overridepublic void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {}@Overridepublic void connectComplete(boolean b, String s) {System.out.println("连接成功!");}});client.connect(options);//连接client.subscribe("test");  //订阅主题// 方式二:只获取当前主题的消息
//        client.subscribe("test", new IMqttMessageListener() {
//            @Override
//            public void messageArrived(String topic, MqttMessage message) throws Exception {
//                System.out.println("接收到消息  topic:" + topic + "  id:" + message.getId() + " message:" + message.toString());
//            }
//        });}

注意:

1. 同一个 Topic 重复订阅会覆盖。

2. clientId 保证唯一,否则容易将其他相同 clientId 的连接顶掉。

相关文章:

MQTT 协议详解:物联网通信的利器

在当今物联网&#xff08;IoT&#xff09;迅猛发展的背景下&#xff0c;设备之间的高效、可靠通信变得尤为重要。MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;作为一种轻量级的消息传输协议&#xff0c;因其低带宽占用和高可靠性&#xff0c;成为物联网领…...

CST软件对OPERACST软件联合仿真汽车无线充电站对人体的影响

上海又收紧了新能源车的免费上牌政策。所以年前一些伙伴和我探讨过买新能源汽车的问题&#xff0c;小伙伴们基本纠结的点是买插电还是纯电&#xff1f;我个人是很抗拒新能源车的&#xff0c;也开过坐过。个人有几个观点&#xff1a; 溢价过高&#xff0c;不保值。实际并不环保…...

C++STL——map和set的使用

目录 1.容器 1.1 序列容器 1.2 容器适配器 1.3 关联容器 1.4 无序关联容器 1.5 键值对到底是个什么东西&#xff1f; 2.set系列的使用 2.1 set类的介绍 2.2 set的构造以及迭代器 2.3 set的增&#xff0c;删&#xff0c;查 2.3.1 插入 2.3.2 删除 2.3.3 查找 2.3.4…...

Ensemble Alignment Subspace Adaptation Method for Cross-Scene Classification

用于跨场景分类的集成对齐子空间自适应方法 摘要&#xff1a;本文提出了一种用于跨场景分类的集成对齐子空间自适应&#xff08;EASA&#xff09;方法&#xff0c;它可以解决同谱异物和异谱同物的问题。该算法将集成学习的思想与域自适应&#xff08;DA&#xff09;算法相结合…...

AFFS2 的 `yaffs_ext_tags` 数据结构详解

YAFFS2 的 yaffs_ext_tags 数据结构详解 yaffs_ext_tags 是 YAFFS2 文件系统中用于 管理 NAND 闪存页的元数据 的核心结构体&#xff0c;存储在 NAND 的 OOB&#xff08;Out-Of-Band&#xff09;区域。它记录了数据块的归属、状态、校验信息等关键元数据&#xff0c;是 YAFFS2…...

CSS经典布局之圣杯布局和双飞翼布局

目标&#xff1a; 中间自适应&#xff0c;两边定宽&#xff0c;并且三栏布局在一行展示。 圣杯布局 实现方法&#xff1a; 通过float搭建布局margin使三列布局到一行上relative相对定位调整位置&#xff1b; 给外部容器添加padding&#xff0c;通过相对定位调整左右两列的…...

超声波传感器模块

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 文章目录 1.HC-SR04介绍2.HC-SR04原理介绍2.1原理概述3.2原理详解 4驱动代码编写4.1写前思考4.2硬件连线 5.总结hcsr04.hhcsr04.c 1.HC-SR04介绍 超声波传感器有很多种类的型号&#xff1a;HC-SR04、UC-025、…...

使用scp命令拷贝hadoop100中文件到其他虚拟机中

以下是使用 scp 命令将 hadoop100 主机中的文件拷贝到其他虚拟机的操作步骤&#xff08;假设其他主机名为 hadoop101 、 hadoop102 &#xff0c;系统为 Linux&#xff09;&#xff1a; 1. 基本语法 bash scp [选项] 源文件路径 目标主机用户名目标主机IP:目标路径 - 选…...

Linux基础 -- 用户态Generic Netlink库高性能接收与回调框架

用户态Generic Netlink库高性能接收与回调框架 一、概述 在 Linux 系统中&#xff0c;Netlink 是用户态与内核态通信的强大机制。libnl 是一个专为简化 Netlink 编程而设计的库&#xff0c;提供了接收和处理 Netlink 消息的高级接口。libnl-genl 是其通用 Netlink (Generic N…...

java中的Optional

在 Java 8 中&#xff0c;Optional 是一个用于处理可能为 null 的值的容器类&#xff0c;旨在减少空指针异常&#xff08;NullPointerException&#xff09;并提升代码的可读性。以下是 Optional 的核心用法和最佳实践&#xff1a; 1. 创建 Optional 对象 1.1 常规创建方式 Op…...

原型和原型链

原型&#xff08;Prototype&#xff09; 和 原型链&#xff08;Prototype Chain&#xff09; 是 JavaScript 中非常重要的概念&#xff0c;它们是 JavaScript 实现继承和共享属性和方法的核心机制。理解原型和原型链可以帮助你更好地掌握 JavaScript 的面向对象编程&#xff08…...

解锁Python TDD:从理论到实战的高效编程之道(9/10)

引言 在 Python 开发的广袤天地中&#xff0c;确保代码质量与稳定性是每位开发者的核心追求。测试驱动开发&#xff08;TDD&#xff0c;Test-Driven Development&#xff09;作为一种强大的开发理念与实践方法&#xff0c;正逐渐成为 Python 开发者不可或缺的工具。TDD 强调在…...

OpenMCU(七):STM32F103开发环境搭建

概述 本文主要讲述了使用Keil软件搭建STM32F103嵌入式开发环境的步骤&#xff0c;主要面向想从事嵌入式行业的入门同学&#xff0c;如果下面的讲述过程中有不对的地方&#xff0c;欢迎大家给我留言。 本文主要讲述了Keil 5.43的安装教程&#xff0c;主要用于学习交流&#xf…...

六、Hive 分桶

作者&#xff1a;IvanCodes 日期&#xff1a;2025年5月13日 专栏&#xff1a;Hive教程 在 Hive 中&#xff0c;除了常见的分区&#xff08;Partitioning&#xff09;&#xff0c;分桶&#xff08;Bucketing&#xff09;是另一种重要且有效的数据组织和性能优化手段。它允许我们…...

INFINI Console 纳管 Elasticsearch 9(一):指标监控、数据管理、DSL 语句执行

Elasticsearch v9.0 版本最近已发布&#xff0c;而 INFINI Console 作为一款开源的非常轻量级的多集群、跨版本的搜索基础设施统一管控平台&#xff0c;是否支持最新的 Elasticsearch v9.0 集群管理呢&#xff1f;本文以 INFINI Console v1.29.2 为例&#xff0c;从指标监控、数…...

ansible进阶版01

ansible进阶版01 欢迎使用Markdown编辑器最佳实践保持简单 保持井然有序&#xff08;有组织的&#xff09;经常测试 git工作原理 chapter 2编写ymal格式的主机清单 欢迎使用Markdown编辑器 最佳实践 保持简单 使用yaml的原生语法使用自带模块尽量使用专用模块&#xff0c;不…...

python文件打包成exe文件

✅ 一、安装 PyInstaller 打开cmd&#xff0c;输入以下代码 pip install pyinstaller✅ 二、打包指令 比如说你有如下的文件需要打包。 首先复制你的文件所在目录&#xff0c;比如我的是C:\Users\Administrator\Desktop\BearingSearchSystem 在cmd中切换到该目录来&#xf…...

人脸识别系统中的隐私与数据权利保障

首席数据官高鹏律师创作 如今人脸识别技术以其高效、便捷的特性广泛应用于各个领域&#xff0c;从安防监控到移动支付&#xff0c;从门禁系统到社交媒体。然而&#xff0c;这项技术在为我们的生活带来诸多便利的同时&#xff0c;也引发了一系列关于隐私与数据权利的深刻担忧。…...

电脑关机再开机会换IP吗?深入解析分配机制

在日常使用电脑时&#xff0c;许多用户可能会好奇&#xff1a;‌关机后再开机&#xff0c;IP地址会不会变化&#xff1f;‌ 这个问题看似简单&#xff0c;但实际上涉及多个因素。本文将详细解析电脑IP地址的变化机制&#xff0c;帮助大家理解其中的原理&#xff0c;并提供相关的…...

经典中的经典-比特币白皮书中文版

AI是一切假的集合&#xff0c;如果任凭AI如此聪明下去&#xff0c;所有的人都将被AI愚弄与股掌之间&#xff0c;那么能限制AI的只有区块链这个让一切数据都无处遁形的真神&#xff0c;而比特币作为区块链的鼻祖&#xff0c;开创了公开账本的先河&#xff0c;当互联网上所有的信…...

Spring事务失效的全面剖析

文章目录 1. Spring事务基础1.1 什么是Spring事务1.2 Spring事务的实现原理1.3 `@Transactional`注解的主要属性1.4 使用Spring事务的简单示例2. Spring事务失效的常见场景及解决方案2.1 方法不是public的问题描述问题示例解决方案技术原理解释2.2 自调用问题(同一个类中的方法…...

本地的ip实现https访问-OpenSSL安装+ssl正式的生成(Windows 系统)

1.下载OpenSSL软件 网站地址&#xff1a;Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions 安装: 一直点击下一步就可以了 2.设置环境变量 在开始菜单右键「此电脑」→「属性」→「高级系统设置」→「环境变量」 在Path 中添加一个: xxxx\OpenSSL-…...

【go】binary包,大小端理解,read,write使用,自实现TCP封包拆包案例

binary.LittleEndian 是 Go 语言 encoding/binary 包中的一个常量&#xff0c;用于指定字节序&#xff08;Byte Order&#xff09;。字节序是指多字节数据在内存中存储的顺序&#xff0c;有两种主要方式&#xff1a; 小端序&#xff08;Little Endian&#xff09;&#xff1a;…...

[万字]qqbot开发记录,部署真寻bot+自编插件

这是我成功部署真寻bot以及实现一个自己编写的插件&#xff08;连接deepseek回复内容&#xff09;的详细记录&#xff0c;几乎每一步都有截图。 正文&#xff1a; 我想玩玩qqbot。为了避免重复造轮子&#xff0c;首先选一个github的高星项目作为基础吧。 看了一眼感觉真寻bot不…...

国内USB IP商业解决方案新选择:硬件USB Server

在数字化办公日益普及的今天&#xff0c;USB OVER NETWORK技术&#xff0c;即USB IP技术&#xff0c;为企业带来了前所未有的便捷与高效。作为这一领域的佼佼者&#xff0c;朝天椒USB Server以其卓越的性能和贴心的设计&#xff0c;正逐步成为众多中国企业的首选USB IP商业解决…...

百度导航广告“焊死”东鹏特饮:商业底线失守,用户安全成隐忧

近日&#xff0c;百度地图因导航时植入“广告”的问题登上社交媒体热搜&#xff0c;并引发广泛争议。 截图自微博 导航途中出现“焊死”在路面的广告 安全隐患引争议 多位网友发帖称&#xff0c;在使用百度地图导航时&#xff0c;导航界面中的公路路面上出现了“累了困了喝东…...

yolo11n-obb训练rknn模型

必备&#xff1a; 准备一台ubuntu22的服务器或者虚拟机&#xff08;x86_64&#xff09; 1、数据集标注&#xff1a; 1&#xff09;推荐使用X-AnyLabeling标注工具 2&#xff09;标注选【旋转框】 3&#xff09;可选AI标注&#xff0c;再手动补充&#xff0c;提高标注速度 …...

GNU Screen 曝多漏洞:本地提权与终端劫持风险浮现

SUSE安全团队全面审计发现&#xff0c;广泛使用的终端复用工具GNU Screen存在一系列严重漏洞&#xff0c;包括可导致本地提权至root权限的缺陷。这些问题同时影响最新的Screen 5.0.0版本和更普遍部署的Screen 4.9.x版本&#xff0c;具体影响范围取决于发行版配置。 尽管GNU Sc…...

无人机避障——如何利用MinumSnap进行对速度、加速度进行优化的轨迹生成(附C++python代码)

&#x1f525;轨迹规划领域的 “YYDS”——minimum snap&#xff01;作为基于优化的二次规划经典&#xff0c;它是无人机、自动驾驶轨迹规划论文必引的 “开山之作”。从优化目标函数到变量曲线表达&#xff0c;各路大神疯狂 “魔改”&#xff0c;衍生出无数创新方案。 &#…...

2025 3D工业相机选型及推荐

3D工业相机是专门为工业应用设计的三维视觉采集设备&#xff0c;能够获取物体的三维空间信息&#xff0c;在智能制造、质量检测、机器人引导等领域有广泛应用。 一、主要类型 1.结构光3D相机 通过投射特定光斑或条纹图案并分析变形来重建三维形状 典型代表&#xff1a;双目结构…...

芋道(yudao-cloud)项目,后端接口报401-账号未登录解决方案

一、需求 最近公司有新的业务需求&#xff0c;调研了一下&#xff0c;决定使用芋道&#xff08;yudao-cloud&#xff09;框架,于是从github&#xff08;https://github.com/YunaiV/yudao-cloud&#xff09;上克隆项目&#xff0c;选用的是jdk17版本的。根据项目启动手册&#…...

动态域名服务ddns怎么设置?如何使用路由器动态域名解析让外网访问内网?

设置路由器的动态域名解析&#xff08;DDNS&#xff09;&#xff0c;通常需先选择支持 DDNS 的路由器和提供 DDNS 服务的平台&#xff0c;然后在路由器管理界面中找到 DDNS 相关设置选项&#xff0c;填入在服务平台注册的账号信息&#xff0c;完成配置后保存设置并等待生效。 …...

论文《Collaboration-Aware Graph Convolutional Network for Recommender Systems》阅读

论文《Collaboration-Aware Graph Convolutional Network for Recommender Systems》阅读 论文概况Introduction and MotivationMethodologyLightGCN 传播形式CIRCAGCNImplementation Experiments 论文概况 论文《Collaboration-Aware Graph Convolutional Network for Recomm…...

Codis集群搭建和集成使用的详细步骤示例

以下是Codis集群搭建和集成使用的详细步骤示例&#xff1a; 环境准备 安装Go语言环境 下载并安装适配操作系统的Go语言版本。配置环境变量GOROOT和GOPATH。 安装ZooKeeper 下载ZooKeeper压缩包&#xff0c;解压并进入目录。复制conf/zoo_sample.cfg为conf/zoo.cfg。启动ZooKe…...

利用比较预言机处理模糊的偏好数据

论文标题 ComPO:Preference Alignment via Comparison Oracles 论文地址 https://arxiv.org/pdf/2505.05465 模型地址 https://huggingface.co/ComparisonPO 作者背景 哥伦比亚大学&#xff0c;纽约大学&#xff0c;达摩院 动机 DPO算法直接利用标注好的数据来做偏好对…...

《数据库原理》部分习题解析

《数据库原理》部分习题解析 1. 课本pg196.第1题。 &#xff08;1&#xff09;函数依赖 若对关系模式 R(U) 的任何可能的关系 r&#xff0c;对于任意两个元组 t₁ 和 t₂&#xff0c;若 t₁[X] t₂[X]&#xff0c;则必须有 t₁[Y] t₂[Y]&#xff0c;则称属性集 Y 函数依赖…...

【HCIA】浮动路由

前言 我们通常会在出口路由器配置静态路由去规定流量进入互联网默认应该去往哪里。那么&#xff0c;如果有两个运营商的路由器都能为我们提供上网服务&#xff0c;我们应该如何配置默认路由呢&#xff1f;浮动路由又是怎么一回事呢&#xff1f; 文章目录 前言1. 网络拓扑图2. …...

基于机器学习的卫星钟差预测方法研究HPSO-BP

摘要 本文研究了三种机器学习方法&#xff08;BP神经网络、随机森林和支持向量机&#xff09;在卫星钟差预测中的应用。通过处理GPS和GRACE卫星的钟差数据&#xff0c;构建了时间序列预测模型&#xff0c;并比较了不同方法的预测性能。实验结果表明&#xff0c;优化后的BP神经…...

机器学习中分类模型的常用评价指标

评价指标是针对模型性能优劣的一个定量指标。 一种评价指标只能反映模型一部分性能&#xff0c;如果选择的评价指标不合理&#xff0c;那么可能会得出错误的结论&#xff0c;故而应该针对具体的数据、模型选取不同的的评价指标。 本文将详细介绍机器学习分类任务的常用评价指…...

AI 检测原创论文:技术迷思与教育本质的悖论思考

当高校将 AI 写作检测工具作为学术诚信的 "电子判官"&#xff0c;一场由技术理性引发的教育异化正在悄然上演。GPT-4 检测工具将人类创作的论文误判为 AI 生成的概率高达 23%&#xff08;斯坦福大学 2024 年研究数据&#xff09;&#xff0c;这种 "以 AI 制 AI&…...

langchain学习

无门槛免费申请OpenAI ChatGPT API搭建自己的ChatGPT聊天工具 https://nuowa.net/872 基本概念 LangChain 能解决大模型的两个痛点&#xff0c;包括模型接口复杂、输入长度受限离不开自己精心设计的模块。根据LangChain 的最新文档&#xff0c;目前在 LangChain 中一共有六大…...

蓝桥杯 10. 全球变暖

全球变暖 原题目链接 题目描述 你有一张某海域 N x N 像素的照片&#xff1a; . 表示海洋# 表示陆地 例如如下所示&#xff1a; ....... .##.... .##.... ....##. ..####. ...###. .......在照片中&#xff0c;“上下左右”四个方向上连在一起的一片陆地组成一座岛屿。例…...

OpenTiny icons——超轻量的CSS图标库,引领图标库新风向

我们非常高兴地宣布 opentiny/icons 正式发布啦&#xff01; 源码&#xff1a;https://github.com/opentiny/icons&#xff08;欢迎 Star ⭐&#xff09; 官网&#xff1a;https://opentiny.github.io/icons/ 图标预览&#xff1a;https://opentiny.github.io/icons/brow…...

python使用OpenCV 库将视频拆解为帧并保存为图片

python使用OpenCV 库将视频拆解为帧并保存为图片 import cv2 import osdef video_to_frames(video_path, output_folder, frame_prefixframe_, interval1, target_sizeNone, grayscaleFalse):"""将视频拆分为帧并保存为图片参数:video_path (str): 视频文件路径…...

[论文阅读]ControlNET: A Firewall for RAG-based LLM System

ControlNET: A Firewall for RAG-based LLM System [2504.09593] ControlNET: A Firewall for RAG-based LLM System RAG存在数据泄露风险和数据投毒风险。相关研究探索了提示注入和投毒攻击&#xff0c;但是在控制出入查询流以减轻威胁方面存在不足 文章提出一种ai防火墙CO…...

机器学习 --- 数据集

机器学习 — 数据集 文章目录 机器学习 --- 数据集一&#xff0c;sklearn数据集介绍二&#xff0c;sklearn现实世界数据集介绍三&#xff0c;sklearn加载数据集3.1 加载鸢尾花数据集3.2 加载糖尿病数据集3.3 加载葡萄酒数据集 四&#xff0c;sklearn获取现实世界数据集五&#…...

在Ubuntu服务器上部署Label Studio

一、拉取镜像 docker pull heartexlabs/label-studio:latest 二、启动容器 &#xff08;回到用户目录&#xff0c;例&#xff1a;输入pwd&#xff0c;显示 /home/<user>&#xff09; docker run -d --name label-studio -it -p 8081:8080 -v $(pwd)/mydata:/label-st…...

机器学习07-归一化与标准化

归一化与标准化 一、基本概念 归一化&#xff08;Normalization&#xff09; 定义&#xff1a;将数据缩放到一个固定的区间&#xff0c;通常是[0,1]或[-1,1]&#xff0c;以消除不同特征之间的量纲影响和数值范围差异。公式&#xff1a;对于数据 ( x )&#xff0c;归一化后的值…...

用vue和go实现登录加密

前端使用CryptoJS默认加密方法&#xff1a; var pass CryptoJS.AES.encrypt(formData.password, key.value).toString()使用 CryptoJS.AES.encrypt() 时不指定加密模式和参数时&#xff0c;CryptoJS 默认会执行以下操作 var encrypted CryptoJS.AES.encrypt("明文&quo…...

服务器制造业中,L2、L6、L10等表示什么意思

在服务器制造业中&#xff0c;L2、L6、L10等是用于描述服务器生产流程集成度的分级体系&#xff0c;从基础零件到完整机架系统共分为L1-L12共12个等级。不同等级对应不同的生产环节和交付形态&#xff0c;以下是核心级别的具体含义&#xff1a; L2&#xff08;Level 2&#xf…...