软件设计
2022-04-09
我们的业务逻辑实际上与程序架构、数据库、缓存等严重耦合在一起,我一直觉得这是一种糟糕的设计。在我的想象中,最完美的情况是程序的核心应该用一种接近自然语言的 DSL(领域特定语言)来完整描述业务逻辑。
开发业务的人,谁关心我们的对象是在堆上还是在栈上,谁关心物理服务器是什么型号,甚至我们连数据库提供的功能都不愿多用,想尽可能减少对指定数据库的依赖。现在的服务网格也在剥离程序自身的一些架构方面的控制逻辑。
随着程序设计不断地剥离非业务逻辑的趋势,在不远的未来,早晚会实现我所想象的这种开发模式。
可能说的有点远,有点大。至少,就程序员熟悉的分层这种拆分复杂逻辑的思想来说,我们应该尽可能只采用程序设计语言的基础语法,没有任何外部依赖地,描述业务逻辑。这样的代码不是更容易理解,更方便审计,更便于维护吗?同时还更健壮。
我觉得我的这些想法和 DDD 不谋而合。
注意:DDD 适用于领域复杂度高、需要长期维护和扩展的业务系统。但对于简单的 CRUD 应用,引入了更多抽象,带来不必要的复杂性,还是应该短平快一些。
注意:重点是灵活应用设计思想,让架构为业务服务,而不是为了架构而架构。
核心思想
- 程序的核心的是业务逻辑的描述,贴近业务,而不是整个系统围绕着数据库,然后业务逻辑和技术实现混杂在一起,分散在程序的各处,可能叫做 XXXController、XXXService、XXXUtil。
- 划分子模块(),不同子模块之间通过 API、消息队列、事件驱动等方式进行通信,而不是共享数据。
- 强调统一描述,对问题的描述中不要增加业务实现的部分,增加团队沟通成本。
比如:订单状态包括用户未支付、用户已支付、商家确认、商家备货、商家发货、物流发货、物流配送、用户签收、订单完成、订单取消、订单退款等等状态,存储在数据库里面可能是一个 int 类型字段,
如果在代码中订单状态变更写的是 setStatus(1)、setStatus(2)、setStatus(3),这样做是非常糟糕的。
如果这样的表述出现在内部沟通中,除了做这个开发的人,其他人看到也是一脸懵。
所以状态的状态
领域驱动设计
DDD(Domain-Driven Design,领域驱动设计)是一种软件设计方法,强调软件设计应该以业务领域为中心,而不是以技术为中心。DDD 由 Eric Evans 在 2003 年提出。

领域驱动设计(Domain-Driven Design,简称 DDD)是一种以 业务需求 为核心的软件设计方法,强调 构建符合业务逻辑的领域模型,并通过 明确的边界 和 良好的架构设计 来提升软件的可维护性和可扩展性。DDD 主要包括两个核心部分:战略设计 和 战术设计。
战略设计(Strategic Design)
战略设计关注如何合理划分业务领域,确定子系统的边界,并定义它们之间的关系。核心概念包括:
界限上下文(Bounded Context)
界限上下文是业务系统中的一个独立单元,包含特定的业务逻辑、数据模型和规则。不同上下文之间通过清晰的接口 进行交互,以避免模型混乱。
领域(Domain)与子域(Subdomain)
- 领域(Domain):指整个业务范畴,例如“电子商务”“订单管理”等。
- 子域(Subdomain):将复杂业务拆分为多个独立子域,例如在电子商务系统中,可能包含“商品管理”“订单管理”“支付处理”等子域。
- 核心子域(Core Subdomain):业务的核心竞争力,最需要投入设计和优化的部分。
- 支撑子域(Supporting Subdomain):为核心业务提供支持的部分,例如 CRM、客服管理等。
- 通用子域(Generic Subdomain):可以复用的领域,如用户认证、日志管理等。
战术设计(Tactical Design)
战术设计关注如何在代码层面 实现领域模型,确保业务逻辑的清晰表达和长期可维护性。核心概念包括:
领域模型(Domain Model)
领域模型是对业务逻辑的抽象,主要由以下组成部分:
- 实体(Entity):具有唯一标识(ID)的对象,状态可能随时间变化,例如“订单”“用户”等。
- 值对象(Value Object):无唯一标识,通常用于描述属性,如“地址”“货币金额”。
- 聚合(Aggregate):由多个实体和值对象组成的业务单元,具有一致性约束。
- 聚合根(Aggregate Root):聚合的核心实体,负责维护聚合内部的一致性,对外提供访问接口。
仓储(Repository)
仓储模式用于 管理实体的持久化,屏蔽底层数据库操作,提供对象级的访问方式。例如 OrderRepository 负责管理订单的存取。
领域服务(Domain Service)
当某些业务逻辑无法归属于单个实体时,使用 领域服务(无状态)。例如“计算订单折扣”可能涉及多个对象,可放在 OrderDiscountService 中。
领域事件(Domain Event)
领域事件用于 表示业务中的重要事件,支持异步处理和系统解耦。例如“订单已支付”可以触发多个后续操作(发货、通知用户等)。
其他类似名词
- BDD(Business-Driven Development,业务驱动开发):强调通过业务需求来驱动开发过程,通常使用自然语言编写测试用例。
- BDD(Behavior-Driven Development,行为驱动开发):强调通过行为来定义软件功能,通常使用 Gherkin 语言编写测试用例。
- FDD(Feature-Driven Development,特性驱动开发):强调通过特性来驱动开发过程,每个特性都是一个可交付的增量。
- TDD(Test-Driven Development,测试驱动开发):强调在编写代码之前先编写测试用例,通过测试驱动代码的实现。
参考资料与拓展阅读
SMS SMPP
2022-04-07
https://en.wikipedia.org/wiki/Short_Message_Peer-to-Peer
https://smpp.org/
Short Message Peer-to-Peer (SMPP) 是一种开放的短信协议。虽然名字中带有 P2P 的字样,但 SMPP 实际上是一种 C/S 协议。
移动 CMPP 协议,联通 SGIP 协议,电信 SMGP 协议,据说他们之间交换信息都是走 SMPP 协议。
常用版本:
根据维基百科的资料,SMPP 之前由 SMS 论坛开发,但是 2007 年,SMS 论坛已经解散了。
数据格式
数据包(PDU (protocol data units, or packets))格式:
header (必需)
command_length 4B
command_id 4B
command_status 4B
sequence_number 4B
body (可选)
'command_length', (60) ... 00 00 00 3C
'command_id', (4) ... 00 00 00 04
'command_status', (0) ... 00 00 00 00
'sequence_number', (5) ... 00 00 00 05
'service_type', () ... 00
'source_addr_ton', (2) ... 02
'source_addr_npi', (8) ... 08
'source_addr', (555) ... 35 35 35 00
'dest_addr_ton', (1) ... 01
'dest_addr_npi', (1) ... 01
'dest_addr', (555555555) ... 35 35 35 35 35 35 35 35 35 00
'esm_class', (0) ... 00
'protocol_id', (0) ... 00
'priority_flag', (0) ... 00
'schedule_delivery_time', (0) ... 00
'validity_period', (0) ... 00
'registered_delivery', (0) ... 00
'replace_if_present_flag', (0) ... 00
'data_coding', (3) ... 03
'sm_default_msg_id', (0) ... 00
'sm_length', (15) ... 0F
'short_message', (Hello Wikipedia) ... 48 65 6C 6C 6F 20 57 69 6B 69 70 65 64 69 61
名词
- SMSC:short message service center,服务器端
或者叫 Messaging Center,简写作 MC
- ESME:extended short message entity,客户端
命令
| Command ID |
Value |
| generic_nack |
0x80000000 |
| bind_receiver |
0x00000001 |
| bind_receiver_resp |
0x80000001 |
| bind_transmitter |
0x00000002 |
| bind_transmitter_resp |
0x80000002 |
| query_sm |
0x00000003 |
| query_sm_resp |
0x80000003 |
| submit_sm |
0x00000004 |
| submit_sm_resp |
0x80000004 |
| deliver_sm |
0x00000005 |
| deliver_sm_resp |
0x80000005 |
| unbind |
0x00000006 |
| unbind_resp |
0x80000006 |
| replace_sm |
0x00000007 |
| replace_sm_resp |
0x80000007 |
| cancel_sm |
0x00000008 |
| cancel_sm_resp |
0x80000008 |
| bind_transceiver |
0x00000009 |
| bind_transceiver_resp |
0x80000009 |
| Reserved |
0x0000000A / 0x8000000A |
| outbind |
0x0000000B |
| Reserved |
0x0000000C - 0x00000014 / 0x8000000B - 0x80000014 |
| enquire_link |
0x00000015 |
| enquire_link_resp |
0x80000015 |
| Reserved |
0x00000016 - 0x00000020 / 0x80000016 - 0x80000020 |
| submit_multi |
0x00000021 |
| submit_multi_resp |
0x80000021 |
| Reserved |
0x00000022 - 0x000000FF / 0x80000022 - 0x800000FF |
| Reserved |
0x00000100 |
| Reserved |
0x80000100 |
| Reserved |
0x00000101 / 0x80000101 |
| alert_notification |
0x00000102 |
| Reserved |
0x80000102 |
| data_sm |
0x00000103 |
| data_sm_resp |
0x80000103 |
| Reserved for SMPP extension |
0x00000104 - 0x0000FFFF / 0x80000104 - 0x8000FFFF |
| Reserved |
0x00010000 - 0x000101FF / 0x80010000 - 0x800101FF |
| Reserved for SMSC Vendor |
0x00010200 - 0x000102FF / 0x80010200 - 0x800102FF |
| Reserved |
0x00010300 - 0xFFFFFFFF |
总结:
| RequestCommandID |
ComandValue |
十进制 |
说明 |
| bind_receiver |
0x00000001 |
1 |
建立接收会话(接收上行) |
| bind_transmitter |
0x00000002 |
2 |
建立发送会话(提交下行) |
| query_sm |
0x00000003 |
3 |
查询 |
| submit_sm |
0x00000004 |
4 |
提交 |
| deliver_sm |
0x00000005 |
5 |
下发(状态报告或上行) |
| unbind |
0x00000006 |
6 |
中断连接 |
| replace_sm |
0x00000007 |
7 |
替换已提交消息 |
| cancel_sm |
0x00000008 |
8 |
取消 |
| bind_transceiver |
0x00000009 |
9 |
建立会话(发送 + 接收) |
| outbind |
0x0000000B |
11 |
通知客户端建立连接(bind_receiver ) |
| enquire_link |
0x00000015 |
21 |
心跳 |
| submit_multi |
0x00000021 |
33 |
批量提交(多个收件人) |
| alert_notification |
0x00000102 |
258 |
- |
| data_sm |
0x00000103 |
259 |
submit/deliver 的替代方案 |
- 响应:对应请求 +
0x80000000
outbind,alert_notification 没有对应响应
- 此外,还有
generic_nack 是通用拒绝响应(0x80000000)
- outbind 的场景是服务器端需要推送信息或状态给客户端
开发者
2022-04-07
BNF,Backus-Naur Form,或者 Backus Normal Form,巴科斯范式
用来准确地描述一种计算机语言的语法规则,所以可以理解成是 “语言的语言”。
约翰·巴科斯(美国)首次在 ALGOL 58 中实现巴科斯范式。彼得·诺尔(丹麦)在 ALGOL 60 之中,进一步发展它的概念并将它的符号加以简化,称其为巴科斯范式(Backus Normal Form)。但高德纳主张应称为巴科斯-诺尔范式(Backus–Naur Form),因为它不算是一种正规形式(Normal Form)。
BNF 有两种常见变体:
- ABNF,扩充巴科斯范式
- EBNF,扩展巴科斯范式
不用深究 BNF,EBNF,ABNF,或者什么 xBNF 之间到底有什么区别,在需要开发语法解析器之前,只用知道这些是现在最主流的语法语言就行了。
这篇文章讨论的就是 Internet 领域常用的 ABNF。
(ABNF)它是由第68号互联网标准定义的,也就是RFC 5234,经常用于互联网工程任务组(IETF)通信协议的定义语言。
规则
ABNF 语法描述就是一组规则,每个规则分成规则名称、规则说明两部分。
PS:规则说明可以引用其他的规则。
拿 RFC#822 Internet Message Format 中的例子:
date-time = [ day-of-week "," ] date FWS time [CFWS]
day-of-week = ([FWS] day-name) / obs-day-of-week
day-name = "Mon" / "Tue" / "Wed" / "Thu" /
"Fri" / "Sat" / "Sun"
date = day month year
PS:这里只是截取的部分,没有列出来的规则在别处声明。
参考资料与拓展阅读
SMS CMPP
2022-04-05
- SMS: Short Message Service, 短信
- GSM: Global System for Mobile Communications,全球移动通信系统
- SP: Service Provider,服务商
- SMG: Short Message Gateway,短信网关, 作为 SMC 对外提供的接口,处理不同系统之间的短信交换(SMC 之间,SP 和 SMC 之间)
部分资料也写作 SMGW,ISMG (Internet Short Message Gateway)
- GNS: Gateway Name Server, 网关名称服务器(汇接网关),类似 DNS
- SMC: Short Message Center,短信中心
- PSTN: Public Switched Telephone Network,公用电话网络
- ISDN: Integrated Services Digital Network,综合数字网络
- MSISDN: Mobile Subscriber Integrated Services Digital Network,移动用户数字网络
- SMPP: Short Message Peer-to-Peer,短信点对点协议 https://smpp.org/
对于开发者,只用了解协议中与 SP 相关的部分,也就是 SP 和 SMG 打交道的部分。
SP 的 SMS 要进入 SMC 需要走 SMG。
手机号的国际规范: ITU-T E.164
中国移动 CMPP (China Mobile Peer to Peer)
https://baike.baidu.com/item/CMPP
中国移动点对点协议
中国移动通信互联网短信网关接口协议
基于 TCP 协议。
说明:为中国移动通信集团公司企业规范。规范中描述了中国移动短信业务中各网元(包括 ISMG、 GNS 和 SP)之间的相关消息的类型和定义。
规范中定义了以下三方面的内容:
- 信息资源站实体与互联网短信网关之间的接口协议;
- 互联网短信网关之间的接口协议;
- 互联网短信网关与汇接网关之间的接口协议。
适用于各 SP 和 ISMG 的开发厂商。
中国联通 SGIP (Short Message Gateway Interface Protocol)
https://baike.baidu.com/item/SGIP
中国联合通信公司短消息网关系统接口协议
SGIP 是的英文缩写,是中国联合通信公司短消息网关系统接口协议。
协议说明
本协议是 SMG 和 SP 之间、SMG 和 GNS 之间、以及 SMG 和 SMG 之间的接口协议,简称 SGIP。
通过应用 SGIP 协议,SP 可以接入到 SMG,实现 SP 应用的一点接入、全网服务;SMG 可以通过 SGIP 协议,实现消息在不同 SMG 之间的路由和转发。同时,SMG 通过该协议也可以和 GNS 通信,以实现各 SMG 和 GNS 之间路由表的同步功能。
适用范围
本协议适用于各 SP 厂商和 SMG 的开发厂商。
- 号码可随意扩展
- 支持全国联通上下行
- 支持 300 字长短信
- 可提供二次开发接口
中国电信 SMGP (Short Message Gateway Protocol)
短消息网关协议
https://baike.baidu.com/item/SMGP
https://wenku.baidu.com/view/fc13c7116c175f0e7cd1379b.html
https://wenku.baidu.com/view/b7f17df0fe4ffe4733687e21af45b307e971f9db.html 3.0.1
https://wenku.baidu.com/view/cf3e1ae4866fb84ae55c8d3a.html 3.0.3
SMGP 协议简称
定义
SMGP 协议是 SMGW 与其它网元设备(除 SMC 外)进行短消息传输的接口协议。
非 SMC 网元设备向 SMGW 发送或从 SMGW 接收短消息,这些非 SMC 网元设备称为 ESME。
通信方式
SMGW 与 ESME 之间共有两种连接方式:长连接和短连接。所谓长连接,指在一个 TCP 连接上可以连续发送多个数据包,在 TCP 连接保持期间,如果没有数据包发送,需要双方发链路检测包以维持此连接。短连接是指通信双方有数据交互时,就建立一个 TCP 连接,数据发送完成后,则断开此 TCP 连接,即每次 TCP 连接只完成一对 SMGP 消息的发送。
跳板机 运维
2022-04-05
架构

Core 是 JumpServer 的核心组件,由 Django 二次开发而来,内置了 Gunicorn Celery Beat Flower Daphne 服务。
Lina 是 JumpServer 的前端 UI 项目,主要使用 Vue,Element UI 完成。
Luna 是 JumpServer 的前端 UI 项目,主要使用 Angular CLI 完成。
- Koko 是 Go 版本的 coco,重构了 coco 的 SSH/SFTP 服务和 Web Terminal 服务。
SSH
- Lion未开源 使用了 Apache 软件基金会的开源项目 Guacamole,JumpServer 使用 Golang 和 Vue 重构了 Guacamole 实现 RDP/VNC 协议跳板机功能。
RDP VNC
- Magnus未开源 是 JumpServer 的数据库安全连接组件,支持多种数据库协议,使用 Golang 实现。
Redis MySQL
- Razor:官网没有提供相关介绍,根据 Release Notes 描述,可能是付费版本的 RDP 录像组件。
Linux 视频
2022-04-04
快捷键
Left/Right:快进, 快退
Up/Down:快进, 快退
[/]:倍速 x0.9, x1.1
{/}:倍速 x0.5, x2
Space (p):暂停/播放
,/.: 暂停,然后逐帧前进,逐帧后退
9/0: 音量
s: 截图
q: 退出
v: 字幕开关
j: 切换字幕
o: 显示进度
f: 全屏开关
i: 显示视频信息
#: 切换音轨
l: 设置循环 A-B 点, 循环播放,清除循环
配置
系统配置:/etc/mpv/mpv.conf
cat /etc/mpv/mpv.conf
hwdec=vaapi
用户配置 (需要自己创建):
~/.config/mpv/mpv.conf
~/.config/mpv/input.conf
~/.config/mpv/fonts.conf
~/.config/mpv/script-opts/osc.conf
no-border
idle=yes
osd-font-size=24
save-position-on-quit
hwdec=auto
screenshot-directory=~/Pictures/Screenshots
screenshot-format=png
screenshot-template="%tY%tm%td-%tH%tM%tS-mpv-%F-%wH%wM%wS%wT"
mkdir -p ~/.config/mpv/scripts ~/.config/mpv/script-opts
find ~/.config/mpv/ -ls
GH=https://raw.githubusercontent.com
wget $GH/jonniek/mpv-menu/master/menu.lua -P ~/.config/mpv/scripts/
wget $GH/jonniek/mpv-playlistmanager/master/playlistmanager.lua -P ~/.config/mpv/scripts/
wget $GH/jonniek/mpv-playlistmanager/master/playlistmanager.conf -P ~/.config/mpv/script-opts/
wget $GH/jonniek/mpv-playlistmanager/master/menu.json -P ~/.config/mpv/script-opts/
WebDev Golang Gin Vue ElementUI
2022-04-03
:) 本文正在编辑中,暂时不提供浏览...
Golang
2022-04-02
- 语法简单
- 确实没有很多语言特性,容易上手,但说什么大道至简,Less is more 等价值观就有点扯了。
- 静态类型、强类型、编译型语言
- 性能
- 并发:自带的协程实现(
goroutine + channel)在开发效率和性能之间达成了一个不错的平衡,非常优秀
- 跨平台
- 接口,反射,GC
- C 嵌入
- 便于工程化:工具链齐全,代码规范严格
- 没有历史负担:但是向前兼容的承诺也是
- Go1 兼容性承诺(最重要特性之一):但是也令人担忧,时间一长,可能就有太重的包袱
- 基于消息传递的通信机制
- 核心开发团队名气非常大
- robert griesemer
- rob pike
- ken thompson
- russ cox
- 生态:有大公司站台,有杀手级项目(Docker, K8S 等)
存在的问题
- 异常处理的设计
- 标准库相对太薄弱
- 生态:缺乏主流框架
- 包管理机制上存在的问题
- 没有泛型(1.18 以前)
场景
开发者 英语
2022-04-02
开发者想必都有耳闻,过去一两年间,因为一些美国政治风波的影响,各大社区都被政治正确问题所困扰,然后有一些相关改名的操作。
PS: 连黑人牙膏(高露洁旗下)都改名 “好来牙膏” 了。
最著名的可能就是 GitHub 中的默认主干分支从 master 改成 main,然后很多项目宣布将主从表述由 master/slave 改成 primary/replica,黑名单 Blacklist 改叫 Denylist 或者 Blocklist。
我最近听说有个叫包容性命名促进会的组织(Inclusive Naming Initiative)。
https://inclusivenaming.org/
他们列了一个清单,将开发过程中常用的一些有冒犯性的词,按照冒犯级别分三类,然后还给出来一些他们建议的替换词。
SMS 网络编程 CMPP
2022-03-29
术语
- ISMG: Internet Short Message Gateway
- SMPP: Short Message Peer to Peer
一个国际上比较通用的短信网关协议
CMPP 可能兼容 SMPP,因为 Wireshark 会将 CMPP 会话识别成 SMPP
- CMPP: China Mobile Peer to Peer
中国移动开发的的短信网关协议
- SMC: Short Message Center
- GNS: Gateway Name Server
相当于 CMPP 网络的路由器
- SP: Service Provider
- SMC: Short Message Control
- ISMG_Id: 网关代码
- SP_Id: SP 企业代码
- SP_Code: SP 服务代码
- Service_Id: SP 业务类型
- MO: 手机发送 Originate
- MT: 手机接收 Terminated
网络连接
CMPP 基于 TCP 协议。可以长连接,也可以短连接。
长连接支持一次连接发送多次 CMPP 消息,没有消息的时候需要维持心跳。
短连接则是一次 CMPP 通信之后就断开连接。
关于心跳:
建议每 3 分钟一次心跳,如果 60 秒内没有心跳响应,应该再次心跳,总共 3 次没有响应就断开连接。
关于重试(网关与 SP 之间,网关之间):
60 秒之后没有响应,立即重试,总共 3 次没有响应就停发。
消息采用并发方式发送,加以滑动窗口流量控制,窗口大小参数 W 可配置,现阶段建议为 16,即接收方在应答前一次收到的消息最多不超过 16 条。
关于短连接:
60 秒超时,重试 2 次。
端口
- 7890 长连接(SP 与网关之间)
- 7900 短连接(SP 与网关之间,网关之间)
- 7930 长连接(网关之间)
- 9168 短连接(网关与 GNS 之间)
数据类型
var Total_Length uint32 // 消息总长度
var Command_Id uint32 // 命令或响应类型
var Sequence_Id uint32 // 消息流水号, 递增, 步长为 1, 循环使用
| 命令 |
Command_Id |
| CMPP_CONNECT |
0x00000001 |
| CMPP_TERMINATE |
0x00000002 |
| CMPP_SUBMIT |
0x00000004 |
| CMPP_DELIVER |
0x00000005 |
| CMPP_QUERY |
0x00000006 |
| CMPP_CANCEL |
0x00000007 |
| CMPP_ACTIVE_TEST |
0x00000008 |
| CMPP_FWD |
0x00000009 |
| CMPP_MT_ROUTE |
0x00000010 |
| CMPP_MO_ROUTE |
0x00000011 |
| CMPP_GET_ROUTE |
0x00000012 |
| CMPP_MT_ROUTE_UPDATE |
0x00000013 |
| CMPP_MO_ROUTE_UPDATE |
0x00000014 |
| CMPP_PUSH_MT_ROUTE_UPDATE |
0x00000015 |
| CMPP_PUSH_MO_ROUTE_UPDATE |
0x00000016 |
RESP Command_Id 则是对应的 Command_Id 最高 4 位为 8,即 0x8X。
SP 与 ISMG 之间的通信
对于一般开发来说就这 7 个接口。
- 建立连接 CMPP_CONNECT
- 断开连接 CMPP_TERMINATE
- 提交信息 CMPP_SUBMIT
- 获取状态 CMPP_DELIVER
- 撤回信息 CMPP_CANCEL
- 查询信息 CMPP_QUERY
只是一些统计信息,我想不到这个接口的应用场景
- 链路检测 CMPP_ACTIVE_TEST
连接 CMPP_CONNECT
var Source_Addr [6]byte // SP_Id
var AuthenticatorSource [16]byte // SP_Code
// md5(Source_Addr + 9 字节 0 + shared secret + timestamp)
// timestamp: MMDDHHMMSS, 月日时分秒, 补 0
var Version uint8 // 版本号, 高 4 位表示主版本号, 低 4 位表示次版本号, 最大 15.15
var Timestamp uint32 // 时间戳, 默认为 0
CMPP_CONNECT_RESP
var Status uint8 // 状态, 0 正确, 1 结构错误, 2 非法源地址, 3 认证错误, 4 版本错误, 5 其他错误
var AuthenticatorISMG [16]byte // ISMG 认证码
// md5(Status + AuthenticatorSource + shared secret)
// 如果认证错误, 此项为空
var Version uint8 // 服务器支持的最大版本号
断开连接 CMPP_TERMINATE
无请求消息体,无响应消息体
提交信息 CMPP_SUBMIT
var Msg_Id uint64 // 消息标识, 网关负责自主生成,SP 留空
var Pk_total uint8 // 消息总条数, 从 1 开始
var Pk_number uint8 // 消息序号, 从 1 开始
var Registered_Delivery uint8 // 是否要求返回状态确认报告, 0 不需要, 1 需要, 2 产生 SMC 话单 (该类型短信仅供网关计费使用,不发送给目的终端)
var Msg_level uint8 // 信息级别, 0 低, 1 中, 2 高
var Service_Id [10]byte // 业务类型
var Fee_UserType uint8 // 计费用户类型, 0 普通用户, 1 行业用户, 2 用户组
var Fee_terminal_Id [32]byte // 被计费用户的号码
var TP_pid uint8 // GSM协议类型, 0 GSM 03.40, 1 CDMA, 2 WCDMA, 3 CDMA2000, 4 联通移动TD专用协议
var TP_udhi uint8 // GSM协议类型
var Msg_Fmt uint8 // 信息格式, 0 ASCII 串, 3 短信写卡操作, 4 二进制, 8 UCS2 编码, 15 含 GB 汉字
var Msg_src [6]byte // 消息发送者, SP_Id
var FeeType [2]byte // 资费类别
var FeeCode [6]byte // 资费代码, 以分为单位
var ValId_Time [17]byte // 存活有效期,格式遵循 SMPP3.3 协议
var At_Time [17]byte // 定时发送时间, YYMMDDhhmmsstnnp, t 是 1/10 秒,nn 是与 UTS 时间的差值 00-48,p `+/-`
var Src_Id [21]byte // 源号码
// SP 的服务代码或前缀为服务代码的长号码,
// 网关将该号码完整的填到 SMPP 协议 Submit_SM 消息相应的 source_addr 字段
// 该号码最终在用户手机上显示为短消息的主叫号码
var DestUsr_tl uint8 // 接收信息的用户数量, 小于 100
var Dest_terminal_Id [][21]byte // 接收短信的用户号码 (MSISDN), 21 * DestUsr_tl
var Msg_Length uint8 // 短消息长度
var Msg_Content []byte // 短消息内容
var Reserve [8]byte // 保留
注意:关于短信群发的问题,若 SP 对于群发消息不要求状态报告的回送时,才可以考虑群发,否则必须逐条发送。
关于 TP_udhi 的解释:
如果 = 1,则需要在 Msg_Content 中加入一个 udhi 头,定义如下:
- 六字节
05 00 03 开头,分别表示剩余 5 字节,xxx,剩余标识长度为 3
第四字节,唯一标识
第五字节,短信条数
第六字节,序号
- 七字节
06 08 04 开头,分别表示剩余 6 字节,xxx,剩余标识长度为 4
第四五字节,唯一标识
第六字节,短信条数
第七字节,序号
CMPP_SUBMIT_RESP
var Msg_Id uint64 // 消息表示, SP 自主生成
var Result uint8 // 结果, 0 正确, 1 消息结构错, 2 命令字错, 3 消息序号重复, 4 消息长度错,
// 5 资费代码错, 6 超过最大信息长, 7 业务代码错, 8 流量控制错, 9~ 其他错误
- MMDDHHMMSS,26 位
月份 4 位, 1-12
日期 5 位, 1-31
小时 5 位, 0-23
分钟 6 位, 0-59
秒钟 6 位, 0-59
- 网关代码,22 位
- 序列号,16 位,递增, 步长为 1, 循环使用
查询 CMPP_QUERY
var Time [8]byte // YYYYMMDD
var Query_Type uint8 // 查询类型, 0 总数查询, 1 按业务类型查询
var Query_Code [10]byte // 查询码, 查询类型为 0 时无效, 查询类型为 1 时此处为业务类型
var Reserve [8]byte // 保留
CMPP_QUERY_RESP
var Time [8]byte
var Query_Type uint8
var Query_Code [10]byte
var MT_TLMsg uint32 // 接收消息总数
var MT_TLusr uint32 // 接收用户总数
var MT_Scs uint32 // 转发成功总数
var MT_WT uint32 // 待转发总数
var MT_FL uint32 // 转发失败总数
var MO_Scs uint32 // 发送成功总数
var MO_WT uint32 // 待发送总数
var MO_FL uint32 // 发送失败总数
送交短信 CMPP_DELIVER
从网关发送出来的消息
var Msg_Id uint64
var Dest_Id [21]byte // 目的号码
var Service_Id [10]byte
var TP_pid uint8
var TP_udhi uint8
var Msg_Fmt uint8
var Src_terminal_Id [21]byte // 源号码
var Registered_Delivery uint8
var Msg_Length uint8
var Msg_Content []byte // Msg_Length
var Reserved [8]byte
var Msg_Id uint64
var Stat [7]byte
// DELIVRD 送达
// EXPIRED 过期
// DELETED 删除
// UNDELIV 未送达
// ACCEPTD 接收
// UNKNOWN 非法
// REJECTD 拒绝
var Submit_time [10]byte
var Done_time [10]byte
var Dest_terminal_Id [21]byte
var SMSC_sequence uint32
SP 等待状态报告 48 小时。
CMPP_DELIVER_RESP
var Msg_Id uint64
var Result uint8
删除短信 CMPP_CANCEL
var Msg_Id uint64
CMPP_CANCEL_RESP
var Success_Id uint8 // 0 成功, 1 失败
链路检测 CMPP_ACTIVE_TEST
无消息体。
CMPP_ACTIVE_TEST_RESP
var Reserved [8]byte