MQTT协议分析

news2024/11/26 12:49:46

目录

一、前言

二、MQTT协议概述

概念  

基本原理

MQTT协议的结构

MQTT的QoS机制

QoS 0:最多一次传输

QoS 1:至少一次传输

QoS 2:恰好一次传输

三、MQTT的应用场景

四、MQTT的优点和缺点

五、MQTT协议的实现

六、实战体验MQTT

七、MQTT协议的未来发展


一、前言

随着物联网和智能化应用的快速发展,对于通信协议的需求越来越多样化和复杂化,对于物联网应用来说,基于TCP/IP的协议MQTT(Message Queuing Telemetry Transport)正逐渐成为主流的协议之一。本文将对MQTT协议的相关概念、基本原理、应用场景等进行介绍和分析。

二、MQTT协议概述

概念  

MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅消息传输协议,它被设计用于低带宽和不稳定的网络环境中,比如远程传感器和移动设备等。它支持一对多的消息传输,可以被广泛应用于物联网、移动应用程序、工业自动化、金融服务等领域。

基本原理

MQTT使用基于TCP/IP协议的可靠传输机制来实现消息传输,并采用发布/订阅模式来处理消息。在MQTT中,发布者将消息发布到一个主题(Topic)上,订阅者则可以订阅该主题,以接收发布者发布的消息。MQTT Broker充当一个中间件来传递这些消息。MQTT支持三种QoS(服务质量)等级,从而实现不同的消息传输可靠性和实时性。此外,MQTT还支持各种各样的客户端,包括C语言、Java、Python等等,因此它被广泛用于物联网、移动应用程序、工业自动化等领域。

MQTT协议的结构

MQTT协议主要由三部分组成,分别是固定头部、可变头部和消息体,其中固定头部和可变头部的长度是固定的,消息体的长度是可变的。

固定头部:固定头部由两个部分组成,第一个字节的前四位表示消息类型(MessageType),剩下的四位是标识符标志(Flag)。前四位二进制可表示16种消息类型,如下图所示:

第一个字节后四位中,DUP表示发布消息的副本,用来保证消息的可靠传输。消息重传时,DUP标志被设置为1。而两位的Qos则表示消息的服务质量(以二进制表示):

  1. 00:最多一次传输
  2. 01:至少一次传输
  3. 10:恰好一次传输
  4. 11:预留标识

RETAIN作为发布保留标识,发布保留标识,表示服务器要保留这次推送的信息,如果有新的订阅者出现,就把这消息推送给它,如果设有那么推送至当前订阅者后释放。

第二个字节为剩余长度,用来保存变长头部和消息体的总大小的,但不是直接保存的。这一字节是可以扩展,其保存机制,前7位用于保存长度,后一部用做标识。当最后一位为 1时,表示长度不足,需要使用二个字节继续保存。

可变头部:可变头部长度根据消息类型不同而不同,一般包括报文标识符(Packet Identifier)和主题(Topic)等信息。

消息体:消息体的长度也根据消息类型不同而不同,主要包括消息正文和可选的附加属性等信息。

对于MQTT协议而言,有以下四种类型的消息体:

  1. CONNECT消息体内容主要是:客户端的ClientID、订阅的Topic、Message以及用户名和密码。
  2. SUBSCRIBE消息体内容是一系列的要订阅的主题以及QoS。
  3. SUBACK消息体内容是服务器对于SUBSCRIBE所申请的主题及QoS进行确认和回复。
  4. UNSUBSCRIBE消息体内容是要订阅的主题。

MQTT的QoS机制

MQTT协议支持三种不同的QoS(服务质量)等级,分别为0、1和2,它们分别代表不同的消息传输可靠性和实时性。下面是三种QoS等级的详细说明:

QoS 0:最多一次传输

消息发布者只发送一次消息,无论它是否被接收。此时消息传输的效率最高,但消息的可靠性最低。

消息丢失情况:当我们使用 QoS 0 传递消息时,消息的可靠性完全依赖于底层的 TCP 协议。而 TCP 只能保证在连接稳定不关闭的情况下消息的可靠到达,一旦出现连接关闭、重置,仍有可能丢失当前处于网络链路或操作系统底层缓冲区中的消息。这也是 QoS 0 消息最主要的丢失场景。

QoS 1:至少一次传输

为了保证消息到达,QoS 1加入了应答与重传机制,发送方只有在收到接收方的 PUBACK 报文以后,才能认为消息投递成功,在此之前,发送方需要存储该 PUBLISH 报文以便下次重传。此时消息传输的效率较高,且消息的可靠性较高。

消息重复情况:对于发送方而言,没有收到回传的PUBACK报文有一下两种情况。

  1. 第一种情况:接收方未收到消息。
  2. 第二种情况:接收方收到了消息,回传的PUBACK报文未到达发送方。

如果是第一种情况,发送方将会重传报文,接收方相当于只收到了一次消息。如果是第二种情况,发送方重传报文,但此时接收方已经收到了这个消息,这就导致接收方收到了重复的消息。虽然在重传时,PUBLUSH报文的DUP标志会被设置为1.表示这是一个重传的报文、但是接收方不能假定自己曾经接受过这个消息,仍然需要将其视作一个全新的消息。

QoS 2:恰好一次传输

发送方和接收方之间进行一个消息确认(PUBREC、PUBREL、PUBCOMP)的三步握手,以确保消息的可靠传输。每一次的QoS 2消息投递,都要求发送方与接收方进行至少两次请求/响应流程。此时消息传输的效率较低,但消息的可靠性最高。

下面是设置QoS为2时的消息发送流程:

  1. 首先,发送方存储并发送QoS 为 2的 PUBLISH 报文以启动一次QoS 2消息的传输,然后等待接收方回复 PUBREC 报文。这一部分与QoS 1基本一致,只是响应报文从 PUBACK 变成了 PUBREC。
  2. 当发送方收到 PUBREC 报文,即可确认对端已经收到了 PUBLISH 报文,发送方将不再需要重传这个报文,并且也不能再重传这个报文。所以此时发送方可以删除本地存储的 PUBLISH 报文,然后发送一个 PUBREL 报文,通知对端自己准备将本次使用的 Packet ID 标记为可用了。与 PUBLISH 报文一样,我们需要确保 PUBREL 报文到达对端,所以也需要一个响应报文,并且这个 PUBREL 报文需要被存储下来以便后续重传。
  3. 当接收方收到 PUBREL 报文,也可以确认在这一次的传输流程中不会再有重传的 PUBLISH 报文到达,因此回复 PUBCOMP 报文表示自己也准备好将当前的 Packet ID 用于新的消息了。
  4. 当发送方收到 PUBCOMP 报文,这一次的 QoS 2 消息传输就算正式完成了。在这之后,发送方可以再次使用当前的 Packet ID 发送新的消息,而接收方再次收到使用这个 Packet ID 的 PUBLISH 报文时,也会将它视为一个全新的消息。

消息去重原理:QoS 2 规定,发送方只有在收到 PUBREC 报文之前可以重传 PUBLISH 报文。一旦收到 PUBREC 报文并发出 PUBREL 报文,发送方就进入了 Packet ID 释放流程,不可以再使用当前 Packet ID 重传 PUBLISH 报文。同时,在收到对端回复的 PUBCOMP 报文确认双方都完成 Packet ID 释放之前,也不可以使用当前 Packet ID 发送新的消息。因此,对于接收方来说,能够以 PUBREL 报文为界限,凡是在 PUBREL 报文之前到达的 PUBLISH 报文,都必然是重复的消息;而凡是在 PUBREL 报文之后到达的 PUBLISH 报文,都必然是全新的消息。一旦有了这个前提,我们就能够在协议层面完成 QoS 2 消息的去重。

三、MQTT的应用场景

MQTT协议被广泛应用于各种领域,如下所示:

物联网应用:MQTT是物联网应用中最常用的协议之一,它支持低带宽、低功耗设备,并且可以轻松地扩展到海量设备。

移动应用程序:MQTT是移动应用程序中使用最广泛的协议之一,它可以为移动应用程序提供可靠的消息传输机制,而且消耗的带宽和电量很低。

工业自动化:MQTT可以被广泛应用于工业自动化领域,用于实时监控和控制生产过程中的各种设备。

金融服务:MQTT可以为金融服务提供可靠的消息传输机制,以保证消息的安全性和可靠性。

四、MQTT的优点和缺点

MQTT协议有以下优点:

  1. 灵活性高。MQTT协议是基于发布/订阅模式来处理消息的,可以很方便地支持一对多的通信模式。
  2. 可扩展性强。MQTT协议支持可靠的消息传输机制,并且可以轻松地扩展到海量设备。
  3. 轻量级。MQTT协议是一种轻量级的协议,适用于低带宽和不稳定的网络环境中,消耗的带宽和电量很低。
  4. 易于实现。MQTT协议具有简单的结构和易于实现的特点,可以在各种硬件平台上运行。

MQTT协议的缺点包括以下几点:

  1. 安全性较低。MQTT协议没有内置的安全机制,需要使用TLS/SSL等加密协议来保证通信的安全性。
  2. 可靠性较低。QoS等级为0的消息只能保证最多一次传输,可能会出现消息丢失的情况。
  3. 消息头较大。MQTT协议的消息头比较大,占用了较大的带宽资源。
  4. 无序传输。MQTT协议的消息传输是无序的,不能保证消息的顺序性。

五、MQTT协议的实现

MQTT协议的实现需要以下几个组件:

MQTT客户端:MQTT客户端可以是任何设备,包括PC、手机、传感器等,它用于连接到MQTT Broker,并发布或订阅消息。

MQTT BrokerMQTT Broker是消息代理服务器,负责接收、存储和转发MQTT消息。

MQTT订阅者:MQTT订阅者用于订阅消息,并接收发布者发布的消息。

MQTT发布者:MQTT发布者用于发布消息,并将消息发送给MQTT Broker。

MQTT协议的实现可以使用多种编程语言,如Java、Python、C++等,还可以使用各种MQTT客户端库和MQTT Broker实现,如Eclipse Mosquitto、EMQ X等。

六、实战体验MQTT

实战体验MQTT协议,我们首先需要一个MQTT Broker,建议使用EMQX作为MQTT Broker,具体的安装方式请自行搜索(建议通过docker安装)。安装完成后,浏览器访问localhost:18083,登录之后出现如下界面,表示安装成功。

可在右上角设置中设置中文。

Maven依赖

<dependency>

        <groupId>org.springframework.integration</groupId>

        <artifactId>spring-integration-mqtt</artifactId>

</dependency>

<dependency>

        <groupId>org.projectlombok</groupId>

        <artifactId>lombok</artifactId>

        <optional>true</optional>

</dependency>

想要发送消息,我们需要用到一个消息发送者,一个消息接受者,一个消息代理服务器。消息发送者和接受者代码如下:

ClientMQTT代码:

@Data
public class ClientMQTT {

    private String topic;
    private String clientId;
    private MqttClient mqttClient;
    private MqttConnectOptions mqttConnectOptions;
    private static String host = "tcp://127.0.0.1:1883";// 协议地址
    private static String userName = "admin";// 账号
    private static String passWord = "123456";// 密码

    public static void main(String[] args) throws MqttException {
        ClientMQTT oneClientMQTT = ClientMQTT.getOneClientMQTT("topic123", "clientId123");
    }

    public ClientMQTT() {
        this.topic = "test";//设置默认的topic 和 clientId;
        this.clientId = "testClientId-003";
    }

    public ClientMQTT(String topic, String clientId) throws MqttException {
        this.topic = topic;
        this.clientId = clientId;
    }

    /**
     * 连接到服务器
     */
    private void start() {
        try {
            // host为主机名,clientid即连接MQTT的客户端ID,一般以唯一标识符表示,MemoryPersistence设置clientid的保存形式,默认为以内存保存
            mqttClient = new MqttClient(host, clientId, new MemoryPersistence());
            // MQTT的连接设置
            mqttConnectOptions = new MqttConnectOptions();
            // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接
            mqttConnectOptions.setCleanSession(true);
            // 设置连接的用户名
            mqttConnectOptions.setUserName(userName);
            // 设置连接的密码
            mqttConnectOptions.setPassword(passWord.toCharArray());
            // 设置超时时间 单位为秒
            mqttConnectOptions.setConnectionTimeout(10);
            // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线,但这个方法并没有重连的机制
            mqttConnectOptions.setKeepAliveInterval(20);
            mqttConnectOptions.setAutomaticReconnect(true);
            // 设置回调
            mqttClient.setCallback(new PushCallback());
            MqttTopic mqttTopic = mqttClient.getTopic(topic);
            //setWill方法,如果项目中需要知道客户端是否掉线可以调用该方法。设置最终端口的通知消息
            mqttConnectOptions.setWill(mqttTopic, "close".getBytes(), 2, true);
            mqttClient.connect(mqttConnectOptions);
            //订阅消息
            int[] Qos = {2};
            String[] topic1 = {topic};
            mqttClient.subscribe(topic1, Qos);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 返回一个Client
     */
    public static ClientMQTT getOneClientMQTT(String topic, String clientId) throws MqttException {
        ClientMQTT client = new ClientMQTT(topic, clientId);
        client.start();
        return client;
    }
}

ServerMQTT代码:

@Data
public class ServerMQTT {

 private static Scanner input = new Scanner(new BufferedInputStream(System.in));
    private static PrintWriter pw = new PrintWriter(System.out);
    private String topic;
    private String clientId;
    private MqttClient mqttClient;
    private MqttTopic mqttTopic;
    private MqttMessage mqttMessage;
    private static String host = "tcp://127.0.0.1:1883";// 协议地址
    private static String userName = "admin";// 账号
    private static String passWord = "123456";// 密码

    public static void main(String[] args) throws MqttException {
        ServerMQTT oneServerMQTT = ServerMQTT.getOneServerMQTT("topic123", "client321");
        while (true) {
            String str = input.next();
            int Qos = input.nextInt();
            ServerMQTT.sendMsg(oneServerMQTT, str, Qos);
        }
    }
    public ServerMQTT() throws MqttException {
        this.topic = "test";//设置默认的topic 和 clientId;
        this.clientId = "testClientId-001";
        mqttClient = new MqttClient(host, clientId, new MemoryPersistence());
        connect();
    }

    public ServerMQTT(String topic, String clientId) throws MqttException {
        this.topic = topic;
        this.clientId = clientId;
        mqttClient = new MqttClient(host, clientId, new MemoryPersistence());
        connect();
    }

    /**
     * 用来连接服务器
     */
    private void connect() {
        MqttConnectOptions options = new MqttConnectOptions();
        // 设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录,这里设置为true表示每次连接到服务器都以新的身份连接
        options.setCleanSession(false);
        options.setUserName(userName);// 设置用户密码
        options.setPassword(passWord.toCharArray());
        options.setConnectionTimeout(10);// 设置超时时间
        options.setKeepAliveInterval(20);// 设置会话心跳时间
        options.setAutomaticReconnect(true);
        try {
            mqttClient.setCallback(new PushCallback());
            mqttClient.connect(options);
            mqttTopic = mqttClient.getTopic(topic);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void publish(MqttTopic topic, MqttMessage message) throws MqttPersistenceException, MqttException {
        MqttDeliveryToken token = topic.publish(message);
        token.waitForCompletion();
    }

    /**
     * 返回一个Server
     */
    public static ServerMQTT getOneServerMQTT(String topic, String clientId) throws MqttException {
        ServerMQTT server = new ServerMQTT(topic, clientId);
        return server;
    }

    /**
     * 发送消息
     */
    public static boolean sendMsg(ServerMQTT server, String msg, int qos) throws MqttException {
        server.mqttMessage = new MqttMessage();
        server.mqttMessage.setQos(qos);
        server.mqttMessage.setRetained(true);
        server.mqttMessage.setPayload(msg.getBytes());
        server.publish(server.mqttTopic, server.mqttMessage);
        return server.mqttMessage.isRetained();
    }
}

PushBack代码:

public class PushCallback implements MqttCallback {

    public void connectionLost(Throwable cause) {
        System.out.println("连接断开,可以做重连");
    }

    public void deliveryComplete(IMqttDeliveryToken token) {
    }

    public void messageArrived(String topic, MqttMessage message) throws Exception {
        System.out.println("接收到topic为:" + topic + " Qos = " + message.getQos() + " 内容为:" + new String(message.getPayload()));
    }
}

首先启动ClientMQTT,然后启动ServerMQTT,可直接通过控制台输入消息和Qos等级发送消息。

七、MQTT协议的未来发展

随着物联网技术的不断发展和应用,MQTT协议将继续发挥重要作用。未来,MQTT协议可能会有以下几个发展趋势:

  1. 安全性和可靠性的提升。MQTT协议的未来发展方向之一是提高安全性和可靠性,例如加强数据加密、身份认证和消息确认等功能。
  2. 实时性的提高。MQTT协议将会逐步优化,提高消息传输的实时性,适用于更多实时应用场景。
  3. 扩展性的增强。MQTT协议将会逐步增强其可扩展性,以满足海量设备的连接和通信需求。
  4. 集成性的提高。MQTT协议将会逐步与其他物联网技术集成,例如传感器、无线网络、云计算等,以支持更多的应用场景。

参考资料

MQTT QoS 0, 1, 2 介绍 | EMQ (emqx.com)

MQTT 协议快速体验 | EMQ (emqx.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/384917.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自己动手写编译器:DFA状态机最小化算法

上一节我们完成了从NFA到DFA的状态机转换&#xff0c;有个问题是状态机并非处于最有状态&#xff1a; 在上图的状态机中&#xff0c;状态6和7其实可以合成一个状态点&#xff0c;本节我们看看如何将这类节点进行合并&#xff0c;使得状态机处于最精简状态(状态4也是终结点&…

KDZD土壤电阻率测试仪

一、简介 KDZD土壤电阻率测试仪专为现场测量接地电阻、土壤电阻率、接地电压、交流电压而精心设计制造的&#xff0c;采用新数字及微处理技术&#xff0c;精密4线法、3线法和简易2线法测量接地电阻&#xff0c;导入FFT(快速傅立叶变换)技术、AFC(自动频率控制)技术&#xff0c;…

基于树莓派4B设计的音视频播放器(从0开始)

一、前言 【1】功能总结 选择树莓派设计一款家庭影院系统,可以播放本地视频、网络视频直播、游戏直播、娱乐直播、本地音乐、网络音乐,当做FM网络收音机。 软件采用Qt设计、播放器引擎采用ffmpeg。 当前的硬件选择的是树莓派4B,烧写官方系统,完成最终的开发。 本篇文章主…

Qt QtCreator 安卓开发环境搭建

踩坑 我的qt是使用在线安装工具安装的&#xff0c;Qt版本使用的是5.15.2&#xff0c;QtCreator版本9.0.2 在网上很多教程都是如下步骤 1.安装qt 2.安装jdk 3.安装android-sdk 4.安装android-ndk 5.配置android设置 例如&#xff1a; https://blog.csdn.net/weixin_51363326/…

【p2p】专利:P2p网络中数据传输的方法、电子设备、装置、网络架构

基于混合CDN的低延时直播P2P技术实践 huya 大佬们的讲座。 而且发表了很多专利: 2018年的,点击直接阅读。 本文是学习笔记 本申请公开了P2P网络中数据传输的方法、电子设备、装置、网络架构,该方法包括步骤:接收服务器发送的数据包,所述数据包由共享资源拆分而成,并由服务…

金山轻维表项目进展自动通知

项目经理作为项目全局把控者&#xff0c;经常要和时间“赛跑”。需要实时了解到目前进展如何&#xff0c;跟进人是那些&#xff1f;哪些事项还未完成&#xff1f;项目整体会不会逾期&#xff1f;特别是在一些大型公司中&#xff0c;优秀的项目经理已经学会使用金山轻维表做项目…

05 Android基础--内部存储与外部存储

05 Android基础--内部存储与外部存储什么是内部存储&#xff0c;什么是外部存储&#xff1f;内部存储与外部存储的代码示例什么是内部存储&#xff0c;什么是外部存储&#xff1f; 1.内部存储与外部存储的存储介质&#xff1a; 内部存储的介质&#xff1a;RAM(内存) 内部ROM …

【连接池】什么是HikariCP?HikariCP 解决了哪些问题?为什么要使用 HikariCP?

文章目录什么是连接池什么是HikariCPHikariCP 解决了哪些问题&#xff1f;为什么要使用 HikariCP&#xff1f;HikariCP 的使用Maven支持数据库什么是连接池 数据库连接池负责分配、管理和释放数据库的连接。 数据库连接复用&#xff1a;重复使用现有的数据库长连接&#xff0…

PayPal轮询收款的那些事儿

想必做跨境电商独立站的小伙伴&#xff0c;对于PayPal是再熟悉不过了&#xff0c;PayPal是一个跨国际贸易的支付平台&#xff0c;对于做独立站的朋友来说跨境收款绝大部分都是依赖PayPal以及Stripe条纹了。简单来说PayPal跟国内的支付宝有点类似&#xff0c;但是PayPal它是跨国…

攒了一冬的甜,米易枇杷借力新电商走出川西大山

“绿暗初迎夏&#xff0c;红残不及春。魏花非老伴&#xff0c;卢橘是乡人。”苏轼文中的卢橘&#xff0c;就是枇杷&#xff0c;在苏轼看来&#xff0c;相较于姚黄魏紫&#xff0c;来自故乡四川的枇杷更为亲近。 四川省攀枝花市米易县是全国枇杷早熟产区之一&#xff0c;得益于…

【存储】RAID2.0+、多路径技术、磁盘可靠性技术

RAID2.0RAID 2.0技术RAID技术发展RAID 2.0软件逻辑对象RAID 2.0基本原理硬盘域Storage Pool & TierDisk Group&#xff08;DG&#xff09;LD&#xff08;逻辑磁盘&#xff09;Chunk&#xff08;CK&#xff09;Chunk Group&#xff08;CKG&#xff09;ExtentGrainVolume &am…

米尔Zynq 7000系列单板的FPGA农业生产识别系统

随着农业生产模式和视觉技术的发展&#xff0c;农业采摘机器人的应用已逐渐成为了智慧农业的新趋势&#xff0c;通过机器视觉技术对农作物进行自动检测和识别已成为采摘机器人设计的关键技术之一&#xff0c;这决定了机器人的采摘效果和农场的经济效率。目前市面上最常见的是基…

MATLAB-Scatter3-三维散点图投影至XYZ三个平面

MATLAB-Scatter3函数可以绘制立体的三维散点图&#xff0c;但有时候需要在该立体图中分析X-Y-Z三者的关系&#xff0c;即1副图呈现出4个信息&#xff0c;XYZ综合信息、XY信息、XZ信息、YZ信息。现有的Scatter3无法实现该功能&#xff0c;本文可实现Scatter3三维立体散点图在三个…

纯手动搭建大数据集群架构_记录011_搭建Nifi_安装部署_搭建集群---大数据之Hadoop3.x工作笔记0172

可以看到左侧,把nifi安装包先上传到服务器,然后,去解压,一样放到opt/software目录,然后解压到/opt/module目录 然后去修改这个配置文件nifi.properties,然后 然后nifi.web.http.port=58080 这里只把 nifi.web.http.port=8080 这个端口改成 58080就可以了. 然后我们进入nifi的bi…

《计算机系统基础》——数据的表示

文章目录《计算机系统基础》——数据的表示移码整数无符号整数 (Unsigned integer)带符号整数&#xff08;Signed integer&#xff09;测试代码浮点数表示范围IEEE 754标准例子规格化数0∞/-∞非数非规格数《计算机系统基础》——数据的表示 移码 &#x1f680;&#x1f680;…

2023年中国人工智能产业趋势报告

易观&#xff1a;尽管2022年人工智能市场发展活跃度不及预期&#xff0c;但2022年对人工智能产业来说无疑是令人激动的一年。年中由DALL-E 2以及其后Stable Diffusion和Midjourney等文本-图像生成模型引起公众对人工智能生成内容的大量关注&#xff0c;年末ChatGPT的横空出世刷…

硬件系统工程师宝典(13)-----PCB的布局“有讲究”

各位同学大家好&#xff0c;欢迎继续做客电子工程学习圈&#xff0c;今天我们继续来讲这本书&#xff0c;硬件系统工程师宝典。上篇我们说到EMC的标准以及提高EMC性能的一些常用方法。今天我们来看看PCB上模块的布局有什么讲究。 模块划分及布局 PCB上模块的划分和布局会影响到…

ATTCK v12版本战术实战研究—持久化(二)

一、前言前几期文章中&#xff0c;我们介绍了ATT&CK中侦察、资源开发、初始访问、执行战术、持久化战术的知识。那么从前文中介绍的相关持久化子技术来开展测试&#xff0c;进行更深一步的分析。本文主要内容是介绍攻击者在运用持久化子技术时&#xff0c;在相关的资产服务…

如何使用固态继电器为恒温器供电

恒温器有两种电源&#xff1a;电池和 24VAC。恒温器需要电池才能不间断地运行。电池消耗的能量尽可能低非常重要&#xff0c;但即使您最大限度地减少消耗&#xff0c;这仍然不是一个用户友好的选择&#xff0c;因为电池会不时需要更换。要降低更换频率&#xff0c;可以使用 24V…

Mysql InnoDB 存储引擎笔记

1 存储引擎 简介 Mysql 存储引擎有多种&#xff1a;包括 MyISAM、InnoDB 和 Memory。 其中MyISAM 和 INNODB 的区别&#xff1a; 事务安全&#xff08;MyISAM不支持事务&#xff0c;INNODB支持事务&#xff09;&#xff1b;外键 MyISAM 不支持外键&#xff0c; INNODB支持外…