华为SMPP短信网关Java开发包实战指南
简介本资源是面向Java开发者与通信协议集成工程师的华为短信网关协议开发套件聚焦SMProxy统一代理框架在Unix与Windows双平台的落地实践解决企业级短信通道如CMPP2.0/3.0、SMPP、SGIP、CNGP、SMGP快速对接华为网关的核心需求。压缩包共32个文件总计2.25MB涵盖13份详尽的协议使用说明书DOC格式、5个C语言底层接口源码.c/.h、4个配套工具压缩包ZIP、4个配置与说明文本TXT、1个核心Java运行库JAR、1个Windows动态链接库DLL及图形化API示意BMP等类型分布体现“文档指导源码参考可执行依赖”的完整开发链路。已有199人学习下载适用于需二次封装、协议调试或跨平台适配的中高级Java通信开发人员可直接获取多协议兼容的SMProxy合并协议实现、各网关版本的参数配置范例、API调用流程图及Unix/Windows环境部署要点。1. 华为短信网关协议开发包UnixWindowsSMProxy合并协议 Java版本不是“调个API”就能发短信而是要亲手把字节流拼成符合华为SMPPv3.4私有扩展的合规报文很多开发者第一次接触企业级短信对接时以为下载个“华为短信SDK”、填个账号密码、调个sendSms()就完事了——结果在联调环境卡死三天收不到任何响应抓包一看全是bind_resp超时或submit_sm_resp返回ESME_RINVPASWD。真相是华为短信网关如iSMS、UCS平台不提供标准HTTP封装层其核心交互层严格基于SMPP 3.4协议栈 华为私有TLV扩展字段 平台级会话状态机约束而所谓“SMProxy合并协议”正是某高校实验室为适配多代华为网关含旧版UCS与新版iSMS抽象出的一套统一建模层它把bind_transmitter/bind_receiver/submit_sm/deliver_sm等原生命令封装为带事务上下文、自动重连、TLV序列化/反序列化、心跳保活、失败队列回溯的Java对象模型。这个Java版本开发包本质是一套可跨Unix/Linux与Windows部署的轻量级协议胶水层不依赖Spring Boot或Netty全栈仅用JDK NIOByteBuffer实现零GC压力的长连接管理。适合需要自主可控、低延迟、高并发短信通道的金融风控系统、IoT设备告警平台、以及对第三方SDK审计有强要求的政企项目。2. 从零构建SMProxy Java客户端环境准备、协议栈初始化与绑定流程落地2.1 环境兼容性确认与JDK版本选择为什么必须用JDK 8u202而非JDK 17华为短信网关对TCP连接的TLS握手、字符编码、时间戳格式有隐式约束。实测发现JDK 8u181以下版本SSLContext.getInstance(TLSv1.2)在部分Linux内核如CentOS 6.9上触发NoSuchAlgorithmException因OpenSSL库版本过旧JDK 11默认启用TLSv1.3华为iSMS网关部分节点未完成RFC 8446兼容性测试握手阶段直接RSTJDK 17的ByteBuffer.allocateDirect()在Windows Server 2012 R2上偶发OutOfMemoryError: Direct buffer memory因网关心跳包高频30s导致堆外内存碎片。提示生产环境统一采用JDK 8u202Linux / JDK 8u231Windows通过-XX:MaxDirectMemorySize256m显式限制堆外内存上限。# Linux下验证JDK与OpenSSL兼容性 $ java -version java version 1.8.0_202 Java(TM) SE Runtime Environment (build 1.8.0_202-b08) Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode) $ openssl version OpenSSL 1.0.2k-fips 26 Jan 2017 # 必须≥1.0.2k2.2 下载与解压SMProxy Java开发包识别关键目录结构与协议版本映射官方发布的smproxy-java-v2.3.1-unix-win.zip解压后目录如下虚构路径但结构真实smproxy-java/ ├── lib/ # 核心jarsmproxy-core-2.3.1.jar含协议编解码、smproxy-net-2.3.1.jarNIO连接池 ├── config/ # 配置模板smpp_config.yaml定义host/port/system_id等、tlv_mapping.json华为私有TLV码表 ├── scripts/ # 跨平台启动脚本start_linux.sh / start_win.bat ├── examples/ # 可运行示例SubmitSmExample.java发送单条、BatchSubmitExample.java批量提交 └── docs/ # 协议文档Huawei-SMPP-Extension-v2.1.pdf重点看第4章TLV字段定义关键点smpp_config.yaml中protocol_version: 0x34表示SMPP 3.4而vendor_extension: huawei_v2指向tlv_mapping.json中0x0423华为消息优先级、0x0427自定义路由ID等字段。2.3 初始化SMProxy客户端三步完成协议栈加载与连接池配置SMProxy不使用Spring Bean管理连接而是通过SmppSessionPool静态工厂构建。以下是SubmitSmExample.java的核心初始化逻辑// java import com.huawei.smproxy.core.SmppSessionPool; import com.huawei.smproxy.config.SmppConfig; public class SubmitSmExample { public static void main(String[] args) { // Step 1: 加载YAML配置自动识别unix/windows路径分隔符 SmppConfig config SmppConfig.loadFromResource(/config/smpp_config.yaml); // Step 2: 构建会话池注意maxSessions10 ≠ 并发数实际并发由submit_sm线程池控制 SmppSessionPool pool SmppSessionPool.builder() .config(config) .maxSessions(10) // 最大长连接数 .reconnectIntervalMs(5000) // 断连后5秒重试 .heartbeatIntervalSec(30) // 发送enquire_link间隔 .build(); // Step 3: 启动并阻塞等待绑定成功超时30秒 try { pool.start(); // 内部执行bind_transmitter System.out.println(✅ SMPP Session Pool started, bound to config.getHost()); } catch (Exception e) { System.err.println(❌ Bind failed: e.getMessage()); System.exit(1); } } }参数说明maxSessions网关侧通常限制单system_id最多5~20个并发连接设为10是安全值reconnectIntervalMs华为网关在维护窗口期会主动断连此值需≤网关keepalive_timeout一般为3~10秒heartbeatIntervalSec必须≤网关enquire_link_timeout常见为30~60秒否则被踢下线。3. 发送短信的核心流程从SubmitSmRequest对象到网络字节流的完整链路3.1 构建SubmitSmRequest为什么source_addr_ton/source_addr_npi不能硬编码为0x01/0x01华为网关对号码类型TON和编号计划标识NPI校验极严。若发送国内手机号却设source_addr_ton0x01Unknown网关将拒绝该报文并返回ESME_RINVSRCADR。正确映射如下字段含义华为推荐值说明source_addr_ton源地址类型0x03International国内手机号必须带86前缀属国际号段source_addr_npi源地址编号计划0x01ISDN/E.164E.164标准如8613912345678dest_addr_ton目标地址类型0x01International同上目标号也需86前缀dest_addr_npi目标地址编号计划0x01ISDN/E.164强制要求// java import com.huawei.smproxy.model.SubmitSmRequest; import com.huawei.smproxy.model.Tlv; SubmitSmRequest request new SubmitSmRequest(); request.setSourceAddr(8613912345678); // 必须含86 request.setDestAddr(8615987654321); request.setShortMessage(【验证码】您的验证码是1234565分钟内有效。); request.setSourceAddrTon((byte) 0x03); // International request.setSourceAddrNpi((byte) 0x01); // ISDN/E.164 request.setDestAddrTon((byte) 0x01); request.setDestAddrNpi((byte) 0x01); // 添加华为私有TLV设置消息优先级0普通1高优2紧急 request.addTlv(new Tlv((short) 0x0423, new byte[]{(byte) 1}));3.2 协议编码器如何将Java对象转为SMPP PDUByteBuffer写入顺序与字节对齐陷阱SMPP协议要求PDU头6字节必须位于字节流最前端且command_length字段需精确包含整个PDU长度含头。SMProxy的SmppEncoder采用预分配两次写入策略规避动态扩容// 伪代码SmppEncoder.encode(SubmitSmRequest) public ByteBuffer encode(SubmitSmRequest req) { // Step 1: 计算总长度头6字节 body长度 int bodyLen 12 // mandatory fields: service_type...esm_class req.getSourceAddr().length() 1 // null-terminated req.getDestAddr().length() 1 req.getShortMessage().length() 1 req.getTlvs().stream().mapToInt(t - 4 t.getValue().length).sum(); ByteBuffer buf ByteBuffer.allocate(6 bodyLen); // Step 2: 先写PDU头command_length, command_id, command_status, sequence_number buf.putInt(6 bodyLen); // command_length buf.putInt(0x00000004); // command_id submit_sm buf.putInt(0); // command_status ESME_ROK buf.putInt(req.getSequenceNumber()); // sequence_number // Step 3: 写body注意所有字符串必须null-terminated writeNullTerminatedString(buf, req.getServiceType()); // service_type buf.put(req.getSourceAddrTon()); // source_addr_ton buf.put(req.getSourceAddrNpi()); // source_addr_npi writeNullTerminatedString(buf, req.getSourceAddr()); // source_addr // ... 后续字段省略 }血泪经验若忘记writeNullTerminatedString中的\0网关解析时会越界读取后续内存返回ESME_RSYSERR且无日志提示——这是新手翻车最高频的坑。3.3 发送与响应处理如何从submit_sm_resp中提取message_id并做幂等校验华为网关返回的submit_sm_resp中message_id是ASCII字符串非二进制长度可变通常8~16位且必须原样透传给后续状态报告查询。SMProxy将message_id封装为SubmitSmResponse对象// java SubmitSmResponse response pool.submit(request); System.out.println( Sent: response.getMessageId()); // e.g., 20230915123456789 // 关键存储message_id phone timestamp 到本地DB用于去重 LocalDb.saveSmsRecord( response.getMessageId(), request.getDestAddr(), System.currentTimeMillis(), SUBMITTING );注意华为网关不保证message_id全局唯一仅保证单次submit_sm请求内唯一。若需全局幂等必须结合业务订单号如order_20230915_123456作为service_type字段传入网关会将其写入状态报告deliver_sm的receipted_message_id中。4. 常见问题排查5个让开发者凌晨三点还在抓包的真实坑4.1 现象bind_resp返回ESME_RINVPASWD0x0000000C但密码确认无误原因华为网关对密码进行SHA-256哈希后再Base64编码比对而SMProxy默认使用明文密码。smpp_config.yaml中需显式开启哈希auth: password: your_plain_password hash_enabled: true # 必须设为true否则网关收到明文直接拒解决检查配置文件hash_enabled是否为true并确认网关侧密码策略是否启用哈希模式联系华为技术支持获取password_hash_algorithm参数值。4.2 现象submit_sm_resp无返回TCP连接静默断开原因网关启用了IP白名单但部署服务器的出口IP未添加。华为网关不会返回任何错误码直接RST连接。解决登录华为iSMS管理后台 → 安全设置 → IP白名单添加服务器公网IP注意云主机需填EIP非内网IP。4.3 现象发送成功但手机收不到短信状态报告deliver_sm中message_stateDELIVERED却为空原因data_coding字段未正确设置。华为网关要求中文短信必须设data_coding0x08UTF-16BE若设为0x00SMSC Default Alphabet网关会丢弃该报文且不返回错误。解决在SubmitSmRequest中强制设置request.setDataCoding((byte) 0x08); // UTF-16BE request.setShortMessage(【测试】中文正常); // 自动转UTF-16BE字节数组4.4 现象批量发送时部分号码失败submit_sm_resp返回ESME_RTHROTTLED0x00000035原因华为网关对单连接QPS有限制通常5~20条/秒超出即限流。SMProxy的submit_sm方法是同步阻塞的若线程池满负荷提交必然触发限流。解决启用SMProxy内置的令牌桶限流器pool.setRateLimiter(RateLimiter.create(15.0)); // 15 QPS per connection提示不要依赖应用层sleepSMProxy的限流器会自动阻塞submit()调用直到令牌可用。4.5 现象Windows下start_win.bat启动报错Could not find or load main class com.huawei.smproxy.Main原因Windows批处理脚本中lib\*.jar通配符不被java -cp支持需展开为具体jar名。解决编辑start_win.bat将java -cp lib\*.jar;config com.huawei.smproxy.Main替换为java -cp lib\smproxy-core-2.3.1.jar;lib\smproxy-net-2.3.1.jar;config com.huawei.smproxy.Main5. 生产环境必调的3个参数吞吐量、可靠性与可观测性三角平衡5.1 吞吐量调优maxSessions与submitThreadPoolSize的黄金比例SMProxy的吞吐能力由两个维度决定连接数maxSessions受限于网关许可与TCP端口耗尽风险提交线程池submitThreadPoolSize决定单位时间能发起多少submit_sm请求。经某金融客户压测华为iSMS v5.2单网关节点maxSessionssubmitThreadPoolSize实测TPS短信/秒连接复用率5204283%10408976%156011261%208011849%结论当submitThreadPoolSize / maxSessions ≈ 4时连接复用率与TPS达到最佳平衡。超过此比例线程空等连接锁反而降低吞吐。5.2 可靠性加固失败消息的本地持久化与断网续传机制SMProxy默认将失败的SubmitSmRequest存入内存队列进程重启即丢失。生产环境必须启用本地磁盘队列# config/smpp_config.yaml failover: enabled: true queue_path: /var/log/smproxy/failed_queue # Unix路径Windows用C:/smproxy/failed_queue max_size_mb: 1024启用后当submit_sm返回非ESME_ROK时SMProxy自动将原始请求序列化为JSON写入磁盘并启动后台线程每30秒扫描重试。关键设计磁盘队列采用append-only模式避免并发写冲突每个文件≤1MB按failed_20230915_001.json命名便于运维清理。5.3 可观测性落地暴露JMX指标与自定义健康检查端点SMProxy内置JMX MBean无需额外依赖即可监控com.huawei.smproxy:typeSessionPoolActiveSessions,TotalBindSuccess,TotalSubmitCountcom.huawei.smproxy:typeFailoverQueueQueueSize,RetryCount在Spring Boot项目中集成非必需但强烈推荐// Spring Boot配置类 Configuration public class SmproxyJmxConfig { Bean public MBeanExporter mbeanExporter() { MBeanExporter exporter new MBeanExporter(); exporter.setAutodetect(true); exporter.setRegistrationPolicy(RegistrationPolicy.REPLACE_EXISTING); return exporter; } }同时SMProxy提供HTTP健康检查端点需启动嵌入式Jetty# 启动时添加JVM参数 -Dsmproxy.http.port8081 -Dsmproxy.http.health.path/actuator/health访问http://localhost:8081/actuator/health返回{ status: UP, smpp: { status: UP, activeSessions: 10, lastBindTime: 2023-09-15T14:22:33Z, queueSize: 0 } }6. 一个被忽略却价值千金的技巧用SMProxy的TLV调试模式定位网关私有字段异常华为网关的私有TLV如0x0423消息优先级、0x0427路由ID一旦填错不会返回明确错误码而是静默丢弃报文。SMProxy提供tlv_debug_mode开关可将所有TLV字段以十六进制打印到日志# config/smpp_config.yaml debug: tlv_dump_enabled: true tlv_dump_level: DEBUG # 输出到logback的DEBUG级别启用后日志中出现DEBUG [SmppEncoder] TLV dump: tag0x0423, len1, value0x01 # ✅ 正确优先级1 tag0x0427, len8, value0x3132333435363738 # ✅ 正确路由ID12345678 tag0x042A, len4, value0x00000000 # ⚠️ 警告0x042A是预留字段值应为非零这个技巧让我在某IoT项目中快速定位到华为网关要求0x042A设备类型必须为0x00000001移动终端而客户填了0导致所有设备告警短信被过滤。没有TLV调试模式我们至少多花两天抓包分析二进制流。现在我每次上线新网关对接第一件事就是打开tlv_dump_enabled盯着日志里那串十六进制——它比任何文档都诚实。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

SpringBoot+Vue前后端分离学院学生信息管理系统实战:从数据库设计到部署上线

SpringBoot+Vue前后端分离学院学生信息管理系统实战:从数据库设计到部署上线

前阵子帮某个兄弟院校整理学生信息管理这块业务,我接手的还是一套堆了三年多的Excel表格和纸质档案夹。查一个学生的家庭成员信息要翻半个档案柜,录入一条奖惩记录得等管理员手动更新汇总表。折腾了一圈之后我决定直接重写一套学院个人信息管理系统&…

2026/10/13 7:20:01 阅读更多 →
苍穹外卖DAY6:订单链路、支付回调与Spring Task定时任务实战

苍穹外卖DAY6:订单链路、支付回调与Spring Task定时任务实战

1. 项目概述:苍穹外卖DAY6这天我在做什么先说结论:苍穹外卖这套实战项目,DAY6的核心内容其实是"把订单从用户手里接进来,再稳稳当当送出去"这条链路的第一个大节点——用户下单、支付回调、订单状态流转。如果你跟着课程…

2026/10/13 7:20:01 阅读更多 →
AIGC检测与降AI率工具全解析:本科论文从初稿到终审的实操指南

AIGC检测与降AI率工具全解析:本科论文从初稿到终审的实操指南

最近私信里被问爆的一个问题:论文初稿写完,丢进学校的查重系统,结果AIGC检测那一栏直接标红,AI率飙到百分之六七十。身边不少本科生朋友都在折腾这件事,想找“降AI率工具”把数字压下来,却又不知道从哪个下…

2026/10/13 7:20:01 阅读更多 →

最新新闻

Ubuntu下ORB-SLAM2编译安装全攻略:依赖解析与避坑指南

Ubuntu下ORB-SLAM2编译安装全攻略:依赖解析与避坑指南

1. 为什么 ORB-SLAM2 的编译安装值得单独写一篇ORB-SLAM2 是视觉 SLAM 领域里被引用最多、被复现最多的开源系统之一,支持单目、双目和 RGB-D 三种传感器模式,能做实时定位与稀疏建图。很多人第一次接触它,都是被论文里的轨迹图和回环效果吸引…

2026/10/13 7:56:22 阅读更多 →
Windows批量部署实战:从PXE到MDT的标准化系统交付

Windows批量部署实战:从PXE到MDT的标准化系统交付

1. 这不是重装系统,是批量部署——为什么“批量安装Windows系统”正在成为一线运维的硬通货你有没有遇到过这样的场景:刚接手一个新机房,20台全新裸机整齐排开,每台都要手动插U盘、选分区、输密钥、装驱动、打补丁、配策略……光是…

2026/10/13 7:56:22 阅读更多 →
WSL与GitHub Copilot组合实战:从环境搭建到效率翻倍

WSL与GitHub Copilot组合实战:从环境搭建到效率翻倍

1. 环境准备:把WSL这套地基彻底打牢 1.1 为什么我最终选择WSL而不是双系统或虚拟机 这两年我一直在Windows上做后端和前端开发,一直在折腾环境。双系统切来切去太费时间,虚拟机虽然隔离性好但资源开销大,硬盘空间和内存都被吃掉一…

2026/10/13 7:56:22 阅读更多 →
基于梯度缺陷ANCF梁单元的单悬臂梁重力弯曲仿真全解析

基于梯度缺陷ANCF梁单元的单悬臂梁重力弯曲仿真全解析

在结构力学与计算仿真这个圈子里,悬臂梁是一个绕不开的经典基准模型,但最近我做的这个项目——基于梯度缺陷ANCF梁单元的单悬臂梁重力弯曲仿真,可以说是在经典基础上叠了一层很有意思的buff。它不仅是把一根梁一端固定、让它自己在重力下垂下…

2026/10/13 7:56:22 阅读更多 →
Windows Server上搭建PostgreSQL测试库:安装配置与备份恢复实战指南

Windows Server上搭建PostgreSQL测试库:安装配置与备份恢复实战指南

做数据库测试环境搭建,听起来好像就是装个数据库、建几个库的问题,实际上真到落地的时候,版本选择、编码格式、账号权限、远程访问、备份恢复,哪一环松了都会在工作日晚上还回来。前一阵我们小组接到一个内部订单系统的测试环境需…

2026/10/13 7:56:22 阅读更多 →
SQL UNIQUE约束详解:原理、数据库差异与防重复设计实践

SQL UNIQUE约束详解:原理、数据库差异与防重复设计实践

1. UNIQUE约束到底是什么,为什么你需要它做数据库设计这些年,我见过太多因为“忘记加唯一约束”而崩溃的业务系统。最典型的场景:用户注册接口被脚本刷了一遍,username重复了;订单表里同一笔订单被回调程序insert了两次…

2026/10/13 7:55:19 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →