Modbus TCP 基础回顾

**

在工业自动化领域,Modbus TCP 是一种广泛应用的通信协议,它基于以太网,为设备之间的通信搭建了桥梁,实现了远程设备的高效控制。Modbus TCP 是 Modbus 协议家族中的一员,它在传统 Modbus 协议的基础上,结合了 TCP/IP 协议的优势,具备高速、稳定的数据传输能力。

Modbus TCP 采用客户端 - 服务器模型进行通信。客户端(主站)负责发起请求,比如读取从设备的寄存器数据,或者向从设备写入控制指令;服务器(从站)则响应客户端的请求,执行相应的操作,并返回结果 。这种模型简单而清晰,使得设备之间的通信有条不紊地进行。在实际应用中,一个客户端可以与多个服务器进行通信,实现对不同设备的集中管理和控制。

在 Modbus TCP 通信中,数据是以特定的帧结构进行传输的。帧结构包含了 MBAP(Modbus 应用协议头部)和 PDU(协议数据单元)两部分。MBAP 头部包含事务标识符(用于匹配请求和响应)、协议标识符(固定为 0,表示 Modbus 协议)、长度字段(指示后续数据的字节数)和单元标识符(标识从站设备)。PDU 则包含功能码和数据字段,功能码定义了具体的操作类型,比如读保持寄存器、写单个线圈等,数据字段则携带了具体的操作数据 。例如,当客户端要读取从站的某个寄存器数据时,请求帧中的功能码会设置为读寄存器的功能码,数据字段会包含要读取的寄存器起始地址和数量等信息。

Modbus TCP 使用 TCP 端口 502 进行通信,这是一个被广泛认可和使用的默认端口 。通过以太网连接,设备之间可以实现长距离、高速率的数据传输,突破了传统串口通信的距离和速度限制。比如在大型工厂中,分布在不同区域的设备可以通过 Modbus TCP 连接到同一个网络,实现数据的实时交互和协同工作。

基于以太网的远程控制原理剖析

(一)以太网通信基石

以太网是一种广泛应用的局域网技术,它为 Modbus TCP 提供了通信的物理基础。以太网的核心原理是通过物理层和数据链路层的协同工作,实现设备之间的数据传输。在物理层,以太网定义了多种传输介质,如双绞线、光纤等,不同的传输介质对应着不同的传输速率和传输距离 。例如,常见的超五类双绞线(Cat5e)通常支持 100Mbps 的传输速率,适用于一般的办公网络;而光纤则能够提供更高的传输速率,如千兆以太网(1Gbps)甚至万兆以太网(10Gbps),常用于数据中心等对带宽要求较高的场景。

在数据链路层,以太网采用了 MAC(媒体访问控制)地址来唯一标识网络中的设备 。MAC 地址是一个 48 位的二进制数,通常以十六进制表示,如 “00:11:22:33:44:55”。当设备发送数据时,数据会被封装成帧,帧中包含了源 MAC 地址和目标 MAC 地址,这样数据就能准确地传输到目标设备。以太网还使用了 CSMA/CD(载波监听多路访问 / 冲突检测)机制(早期以太网,现在全双工模式下基本避免冲突)来解决多个设备同时访问传输介质时可能产生的冲突问题 。当一个设备要发送数据时,它会先监听传输介质,如果介质空闲,就开始发送数据;在发送数据的同时,设备还会检测是否发生冲突,如果检测到冲突,就会停止发送,并发送一个干扰信号,通知其他设备发生了冲突,然后等待一个随机的时间后再次尝试发送。

在工业自动化中,以太网的稳定性和高速率为远程设备控制提供了坚实的通信基础。它能够确保大量的设备数据,如传感器数据、设备状态信息等,能够快速、准确地传输到控制中心,为实时监控和控制提供了有力支持 。例如,在汽车制造工厂中,生产线上分布着大量的机器人、传感器和控制器,它们通过以太网连接在一起,实现了生产过程的自动化控制和监控。一旦某个设备出现故障,相关的故障信息能够迅速通过以太网传输到监控中心,工作人员可以及时采取措施进行处理,从而提高了生产效率和设备的可靠性。

(二)Modbus TCP 协议深度解析

1. 协议架构

Modbus TCP 基于 TCP/IP 协议栈,它位于应用层,利用了 TCP 协议的可靠传输特性和 IP 协议的网络寻址功能 。在 TCP/IP 协议栈中,网络层的 IP 协议负责将数据包从源地址传输到目标地址,它通过路由选择算法确定数据包的传输路径;传输层的 TCP 协议则提供了可靠的、面向连接的通信服务,它通过三次握手建立连接,在数据传输过程中进行流量控制和差错校验,确保数据的完整性和顺序性。

Modbus TCP 采用客户端 - 服务器的通信模式 。客户端是发起通信请求的设备,它通常是上位机,如监控计算机、SCADA( Supervisory Control And Data Acquisition,数据采集与监视控制系统)系统等;服务器是响应客户端请求的设备,一般是现场的工业设备,如 PLC(可编程逻辑控制器)、智能仪表、传感器等。当客户端要与服务器进行通信时,首先会通过 TCP 协议与服务器建立连接,连接建立成功后,客户端会向服务器发送请求报文,服务器接收到请求后,会解析请求报文,执行相应的操作,并返回响应报文给客户端 。例如,客户端向服务器发送读取寄存器数据的请求,服务器在接收到请求后,会从相应的寄存器中读取数据,然后将数据封装在响应报文中返回给客户端。

2. 数据传输与功能码

在 Modbus TCP 中,数据是以特定的帧格式进行传输的 。帧由 MBAP 头部和 PDU 组成。MBAP 头部包含事务标识符、协议标识符、长度字段和单元标识符。事务标识符由客户端生成,用于匹配请求和响应,确保客户端能够正确识别接收到的响应是对应哪个请求的;协议标识符固定为 0,表示 Modbus 协议;长度字段指示后续数据(包括单元标识符和 PDU)的字节数;单元标识符用于标识从站设备,如果是广播通信,单元标识符通常设置为 0xFF 。

PDU 包含功能码和数据字段。功能码是 PDU 的关键部分,它定义了客户端请求的具体操作类型 。常见的功能码有:

  • 读线圈(功能码 01):用于读取从站设备的线圈状态(开关量),例如可以读取某个阀门的开 / 关状态 。假设客户端要读取从站地址为 1 的设备的第 10 个线圈状态,请求帧中的功能码为 01,数据字段中会包含起始线圈地址(如 0x0009,因为地址从 0 开始)和读取的线圈数量(0x0001) 。
  • 读离散输入(功能码 02):用于读取从站设备的离散输入状态,离散输入通常是外部的开关信号,如按钮的按下 / 松开状态 。例如,客户端读取从站地址为 2 的设备的前 10 个离散输入状态,功能码为 02,数据字段包含起始离散输入地址(0x0000)和读取数量(0x000A) 。
  • 读保持寄存器(功能码 03):用于读取从站设备的保持寄存器数据,保持寄存器可以存储各种类型的数据,如温度、压力、流量等测量值 。比如,客户端读取从站地址为 3 的设备的从地址 0 开始的 5 个保持寄存器数据,功能码为 03,数据字段包含起始寄存器地址(0x0000)和读取数量(0x0005) 。
  • 写单个线圈(功能码 05):用于向从站设备的单个线圈写入状态,可实现对设备的控制,如控制电机的启动 / 停止 。若客户端要将从站地址为 4 的设备的第 5 个线圈设置为闭合状态,功能码为 05,数据字段包含线圈地址(0x0004)和写入值(0xFF00 表示闭合,0x0000 表示断开) 。
  • 写单个保持寄存器(功能码 06):用于向从站设备的单个保持寄存器写入数据,例如设置设备的某个参数值 。例如,客户端将从站地址为 5 的设备的第 8 个保持寄存器写入值为 100 的数据,功能码为 06,数据字段包含寄存器地址(0x0007)和写入数据(0x0064) 。

Modbus TCP 进阶技术要点

(一)通信效率优化秘籍

1. 网络延迟与吞吐量优化策略

网络延迟和吞吐量是影响 Modbus TCP 通信效率的关键因素 。网络延迟指的是数据包从发送端传输到接收端所经历的时间,它会导致数据传输的延迟,影响设备之间的实时交互。例如,在远程监控系统中,如果网络延迟过高,监控画面可能会出现卡顿,操作人员无法及时获取设备的实时状态,从而影响对设备的控制和管理 。吞吐量则是指单位时间内成功传输的数据量,吞吐量较低会限制数据的传输速度,导致大量数据积压,降低系统的整体性能 。

为了减少网络延迟,提高吞吐量,可以采取以下方法:

  • 选用优质网络设备:使用高性能的交换机、路由器等网络设备,它们具备更快的处理速度和更大的缓存空间,能够快速转发数据包,减少数据包的排队等待时间,从而降低网络延迟 。比如,企业级的千兆交换机相比普通的百兆交换机,能够提供更高的带宽和更低的延迟,更适合工业自动化场景中大量数据的快速传输 。
  • 优化网络拓扑:合理设计网络拓扑结构,减少网络中的中转节点和不必要的网络链路,缩短数据传输的物理路径,降低信号衰减和干扰,进而减少网络延迟 。例如,采用星型拓扑结构,所有设备都连接到中心交换机,这种结构简单清晰,便于管理和维护,能够有效提高网络的可靠性和传输效率 。
  • 实施流量控制:通过设置合适的流量控制策略,如令牌桶算法、漏桶算法等,合理分配网络带宽,避免网络拥塞,确保数据包能够按照一定的速率发送和接收,提高吞吐量 。比如,当网络中的数据流量过大时,流量控制机制可以限制某些设备的发送速率,优先保证关键设备的数据传输,从而维持网络的稳定运行 。
  • 使用高速链路:选择高速的网络传输介质,如光纤,光纤具有带宽高、损耗低、抗干扰能力强等优点,能够提供更高的传输速率和更低的延迟,满足工业自动化对数据传输速度和稳定性的要求 。在一些对数据传输要求极高的场景,如大型数据中心、高清视频监控系统等,光纤已经成为主流的传输介质 。
2. 数据封装与传输优化实践

在 Modbus TCP 通信中,数据封装与传输的优化对于提高通信效率至关重要 。

  • 设置合适 MTU 大小:MTU(最大传输单元)是指网络设备能够传输的最大数据包大小 。如果 MTU 设置过小,数据包会被分割成多个小片段进行传输,增加了传输的开销和延迟;如果 MTU 设置过大,可能会导致数据包在传输过程中因网络链路的限制而无法正常传输,需要进行分片和重组,同样会影响传输效率 。因此,需要根据网络环境和设备性能,合理设置 MTU 大小 。一般来说,以太网的默认 MTU 值为 1500 字节,但在一些特殊情况下,如通过 VPN 连接或者网络中存在老旧设备时,可能需要适当调整 MTU 值 。可以通过网络测试工具,如 ping 命令,来测试不同 MTU 值下的网络性能,找到最佳的 MTU 设置 。例如,使用命令 “ping -l [数据包大小] -f [目标 IP 地址]”,其中 “-l” 参数指定数据包大小,“-f” 参数表示不允许数据包分片,通过逐步调整数据包大小并观察 ping 命令的响应时间和丢包率,来确定合适的 MTU 值 。
  • 启用 TCP 窗口缩放:TCP 窗口缩放是一种提高 TCP 性能的技术,它允许在 TCP 会话中使用较大的窗口尺寸,从而提高网络的吞吐量 。在高延迟和高带宽的网络环境中,启用 TCP 窗口缩放尤为重要 。例如,在跨地区的工业自动化系统中,数据需要经过长距离的网络传输,延迟较高,此时启用 TCP 窗口缩放可以使发送方能够一次性发送更多的数据,减少数据传输的往返次数,提高数据传输效率 。在 Linux 系统中,可以通过修改系统参数 “net.ipv4.tcp_window_scaling” 来启用 TCP 窗口缩放,将其值设置为 1 即可 。在 Windows 系统中,可以通过修改注册表来启用 TCP 窗口缩放,具体方法是在注册表中找到 “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters”,新建一个 DWORD 值 “TcpWindowSize”,并设置合适的值(一般建议设置为 65535) 。

(二)自定义功能码拓展应用

1. 自定义功能码原理

标准的 Modbus 功能码虽然覆盖了常见的数据读写、设备诊断等操作,但在实际的工业自动化应用中,由于不同设备的功能和需求各异,标准功能码可能无法满足所有的业务需求 。这时,自定义功能码就发挥了重要作用 。自定义功能码是 Modbus 协议中用于扩展标准功能码的一种机制,它允许用户根据特定应用需求来开发新的功能 。通过自定义功能码,用户可以实现一些标准功能码无法完成的操作,如读取特定设备的非标准寄存器数据、执行特定的设备控制算法等,从而增加了 Modbus 协议的灵活性和应用范围 。

自定义功能码的工作原理是在 Modbus 协议的框架内,用户自行定义功能码的值以及该功能码对应的操作 。当客户端发送包含自定义功能码的请求时,服务器能够识别该功能码,并根据预先定义的规则执行相应的操作,然后将结果返回给客户端 。例如,在一个智能工厂的设备管理系统中,为了实现对某台特殊设备的能源消耗监测和分析,开发人员可以自定义一个功能码,该功能码用于读取设备的实时能源消耗数据,并进行一些特定的计算和处理,然后将处理后的结果返回给上位机,以便管理人员进行分析和决策 。

2. 实现步骤与案例展示

以三菱 PLC 为例,介绍自定义功能码的实现步骤 。

  • 第一步:确定需求和功能定义:明确需要实现的特殊功能,例如读取设备的自定义状态信息、执行特定的设备控制逻辑等 。根据功能需求,定义自定义功能码的值,确保该值在 Modbus 协议的未使用功能码范围内 。假设我们要实现一个读取三菱 PLC 特定区域内存数据的功能,自定义功能码设置为 0x90 。
  • 第二步:编程实现功能逻辑:使用三菱 PLC 的编程软件,如 GX Works2,编写实现自定义功能的程序逻辑 。在程序中,根据自定义功能码的值,编写相应的代码来处理请求 。例如,当接收到功能码为 0x90 的请求时,程序会读取特定内存区域的数据,并将数据打包成响应帧 。下面是一个简单的示例代码(以梯形图语言为例):
 

// 假设自定义功能码存储在D100中

LD D100 = 0x90 // 判断是否为自定义功能码

JMP Z, NOT_CUSTOM_FUNCTION // 如果不是,跳转到非自定义功能处理

// 自定义功能处理

// 读取特定内存区域数据,假设数据存储在D200 - D209

MOV D200, R0 // 将数据存储到响应数据区

MOV D201, R1

// 依次类推,将D202 - D209的数据存储到R2 - R9

// 构建响应帧,假设响应帧存储在D300 - D310

MOV 0x90, D300 // 功能码

// 将读取的数据存储到响应帧的相应位置

MOV R0, D301

MOV R1, D302

// 依次类推

JMP END_PROGRAM // 跳转到程序结束

NOT_CUSTOM_FUNCTION:

// 非自定义功能处理,执行标准功能码的操作

END_PROGRAM:

  • 第三步:配置 PLC 通信参数:确保 PLC 的网络参数配置正确,包括 IP 地址、子网掩码、网关等 。同时,需要设置 PLC 支持自定义功能码的解析和处理 。在 GX Works2 中,可以在通信参数设置界面中进行相关配置,使 PLC 能够识别并处理自定义功能码的请求 。
  • 第四步:测试与验证:使用 Modbus TCP 客户端工具,如 Modbus Poll 等,向三菱 PLC 发送包含自定义功能码的请求,验证自定义功能是否正常工作 。在测试过程中,检查响应数据是否正确,功能是否符合预期 。例如,使用 Modbus Poll 发送功能码为 0x90 的请求,查看是否能够正确读取到 PLC 特定内存区域的数据,并与预期结果进行对比 。

实际应用案例:在一个自动化生产线中,有一台三菱 PLC 控制着关键设备的运行 。为了实现对设备的精细化管理和故障预测,需要获取设备的一些内部状态信息,这些信息无法通过标准功能码获取 。通过自定义功能码,开发人员实现了读取设备运行时间、累计工作次数、关键部件温度等信息的功能 。上位机通过发送自定义功能码的请求,能够实时获取这些信息,并进行数据分析和处理 。当设备运行时间达到一定阈值或者关键部件温度过高时,系统会及时发出警报,提醒维护人员进行检查和维护,有效提高了设备的可靠性和生产效率 。

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux魔术字定位踩内存总结

0,数据被改写时我们需要怎么定位,我们首先需要确认数据是逻辑上被改写还是踩内存被改写的。 1,当数据被踩时,也就是出现数据异常时,并且可以稳定复现时,我们确认时踩固定内存时,我们可以使用魔术字定位问题。 代码举例查看确认。 #include <stdio.h> #include…

浅谈Docker Kicks in的应用

正因为传统部署的麻烦&#xff0c;我们希望减少整个安装过程&#xff0c;将其简单化&#xff0c;以下介绍两个思路&#xff1a; 思路一&#xff1a;安装 Docker 后安装 Ghost&#xff0c;并且直接暴露 80 端口&#xff0c;此时所有请求由 Docker 内的 Express 服务器处理&…

【Rust + Actix Web】现代后端开发:从零构建高并发 Web 应用

目录 项目概述环境准备项目创建与依赖配置系统架构设计核心代码实现1. 数据库模型 (src/models.rs)2. 应用状态管理 (src/state.rs)3. 核心业务逻辑 (src/handlers.rs)4. 主应用入口 (src/main.rs) 高并发优化策略1. 异步处理模型2. 连接池配置优化3. 缓存策略设计 性能测试结果…

2025java面试题整理通俗易懂好记

一、Java 基础 1. JVM 相关 Q&#xff1a;什么情况下会发生栈内存溢出&#xff1f; A&#xff1a;就像食堂打饭窗口前排队&#xff0c;队伍太长&#xff08;方法调用层级太深&#xff09;&#xff0c;或者每个人占的位置太大&#xff08;局部变量太多&#xff09;&#xff0c;…

内存分配算法(系统分配算法~应用常见算法)

一、内存碎片 内部碎片与外部碎片 内部碎片&#xff1a;指已分配给进程但未被实际利用的内存空间&#xff0c;属于​​已分配内存内部的浪费​​。 外部碎片&#xff1a;内存中​​零散分布的空闲小空间​​&#xff0c;总量足够但无法合并为大块以满足连续内存请求。 内部碎…

缓解停车难的城市密码:4G地磁检测器如何重构车位资源分配

城市停车难&#xff0c;是困扰车主和管理者的双重痛点。寻找车位耗时耗力&#xff0c;人工计时收费易生纠纷&#xff0c;传统管理模式效率低下。而 4G地磁检测器 的出现&#xff0c;正悄然改变这一局面。它如同埋入城市道路的“感知神经元”&#xff0c;通过4G地磁检测器 的精准…

【网工|查缺补漏】存储与RAID技术①

目录 ■存储基础 ▲存储系统层次结构 ▲存储介质选择 ▲硬盘接口 ■传统RAID技术 ▲RAID数据组织及存取方式 ▲RAID热备与重构 ▲常用RAID技术 ■RAID2.0技术 ▲RAID2.0技术优势 ■网络存储体系DAS/NAS/SAN ▲DAS (Direct Attached Storage) ▲FC SAN (Fiber Chan…

ESP官网的使用手册网址

LED Control (LEDC) — Arduino-ESP32 2.0.14 documentation (readthedocs-hosted.com) 中文网站&#xff1a;红外遥控 (RMT) - ESP32 - — ESP-IDF 编程指南 v5.4.2 文档 (espressif.com)

网络基础知识与代理配置

网络基础知识 OSI七层模型与协议对应 OSI层功能典型协议应用层网络服务接口&#xff0c;为应用程序提供网络服务HTTP, HTTPS, FTP, SMTP, DNS, Telnet, SSH表示层数据格式化、代码转换、数据加密解密SSL/TLS, JPEG, GIF, ASCII, 压缩算法会话层建立、管理和终止会话连接NetBI…

Windows 疑难杂症集 - MsMpEng.exe 磁盘占用率持续高占

本系列记录日常使用中遇到的一些问题及处理方法。系统环境为 Windows 10&#xff0c;但可能也适用于 Windows11&#xff0c;甚至也会包含部分 Windows7 等老系统环境。 有的时候感觉系统异常卡顿&#xff0c; CtrlShiftEsc 打开任务管理器&#xff0c;看到某个磁盘居然IO达到了…

《UE5_C++多人TPS完整教程》学习笔记40 ——《P41 装备(武器)姿势(Equipped Pose)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P41 装备&#xff08;武器&#xff09;姿势&#xff08;Equipped Pose&#xff09;》 的学习笔记&#xff0c;该系列教学视频为计算机工程师、程序员、游戏开发者、作家&#xff08;Engineer, Programmer, Game Develop…

【HarmonyOS】鸿蒙使用仓颉编程入门

【HarmonyOS】鸿蒙使用仓颉编程入门 一、前言 仓颉&#xff0c;是华为自研的一款面向全场景智能的新一代编程语言&#xff0c;是为鸿蒙量身打造的全场景智能应用编程语言&#xff0c;作为鸿蒙生态中的重要组成部分&#xff0c;旨在支持鸿蒙系统下的全场景应用开发 &#xff0…

2.3.1 Nginx Web服务器安全加固

文章目录 一、试题及考试说明二、操作步骤1. 启动Nginx服务2. 隐藏站点 Response Header 里的Web服务版本信息&#xff08;见下总图&#xff09;3. 隐藏站点 Response Header 里的X-Powered-By 字段&#xff08;见下总图&#xff09;4. Nginx访问日志存放位置修改为/opt/bak/ac…

红色背景政府当讲PPT模版

政府党建PPT模版&#xff0c;庆国庆PPT模版&#xff0c;国庆节PPT模版 红色背景政府当讲PPT模版&#xff1a;https://pan.quark.cn/s/a6f484905430

JavaScript对象(Object)常用操作

创建对象 //使用对象字面量、构造函数或者Object.create()方法来创建对象// 对象字面量 const person {name: John,age: 30,hobbies: [reading, swimming] };// 构造函数 function Car(make, model) {this.make make;this.model model; } const myCar new Car(Toyota, Cor…

Java面试宝典:基础一

⚙️ 1. Java跨平台原理&#xff08;字节码文件与JVM&#xff09; 核心机制&#xff1a; Java源程序&#xff08;.java&#xff09;编译为与平台无关的字节码文件&#xff08;.class&#xff09;&#xff0c;而非直接生成机器码。字节码由**Java虚拟机&#xff08;JVM&#xf…

uniapp微信小程序:editor组件placeholder字体样式修改

一、问题描述 微信小程序editor组件的placeholder字体默认为斜体字&#xff0c;官方对此没有属性可以设置它的样式&#xff0c;并且直接在组件上设置样式也是无效的。 二、解决方案 通过审查节点&#xff1a; 可以看到editor的placeholder其实是在一个伪元素上。 在页面或者…

PhoneRescue 4.3绿色版!解决iPhone数据丢失、系统崩溃等场景

目录 一、引言二、软件介绍1. 研发背景与定位2. 兼容性与技术优势 三、功能介绍1. 数据恢复功能&#xff08;核心痛点解决方案&#xff09;2. 系统修复功能3. 数据管理辅助 四、软件特色1. 操作极简&#xff0c;零技术门槛2. 安全可靠&#xff0c;零数据风险3. 高效精准&#x…

Vue 快速入门

一、Vue是什么 Vue是一款用于构建用户界面的渐进式的JavaScript框架。 官网&#xff1a;Vue.js - 渐进式 JavaScript 框架 | Vue.js 其核心特性包括&#xff1a; 响应式数据绑定&#xff1a;通过 Vue 的响应式系统&#xff0c;数据变化会自动反映到视图&#xff0c;减少手动 D…

JAVA-JWT

JWT简介 JSON Web Token&#xff08;JWT&#xff09;是一个非常轻巧的规范&#xff0c;这个规范允许我们使用 JWT 在用户和服务器之间传递安全可靠的信息。一个 JWT 实际上就是一个字符串&#xff0c;它由三部分组成&#xff0c;头部、载荷与签名。前两部分需要经过 Base64 编…