# 什么是 SMPP？企业短信背后的那条长连接

SMPP 是平台与短信中心之间交换短消息的协议，跑在一条持续打开的会话上。绑定声明方向，会话带着吞吐窗口，送达回执以 PDU 返回。它不是一问一答的 API。

- SMPP 是一条持续打开的会话，绑定时声明方向。

- 一个绑定承载一份吞吐配额和一个在途请求窗口。

- 一条 PDU 有 16 字节头部，报文体随命令而变。

- 送达回执异步返回，按 message ID 匹配。

## 是会话，不是一次调用

SMPP 在您的平台和短信中心之间保持一条连接。平台认证一次，声明要做什么，之后就在同一条会话上提交消息、接收事件。短信中心不必等新的请求才发回执或上行的短信。有结果要报时，它直接推一条 PDU 过来。
这种形态适合稳定的流量。会话状态已经建好，回执通道也一直开着，单条消息的开销就小。代价是客户端要自己管状态：绑定是否正常、在途窗口用了多少、心跳什么时候发、断线后怎么重连。这些在 HTTP 客户端里都不存在。

## 绑定声明方向

绑定就是通过认证的会话加一个方向。发送绑定（transmitter）用来提交消息，接收绑定（receiver）用来接收手机发起的消息和回执，收发绑定（transceiver）在一条会话里兼顾两者。服务商为每种绑定发凭据，也可能限制您能开几条。
扩容靠加绑定，不是把一条绑定推到配额之外。一条绑定对应一份吞吐配额和一个在途窗口。峰值不够，就再申请一条绑定，把流量摊开。一条绑定被推过窗口，换来的只会是限流、超时和重试。看起来像网络故障，根子在客户端。

### 绑定、提交、回执

会话只开一次，每次提交拿到带 message ID 的响应，回执稍后沿同一条会话返回。

Alt: 从应用发出绑定请求，到短信中心、提交响应和送达回执的时序。

应用打开绑定，短信中心返回响应。应用用 submit_sm 提交一条短信，收到带 message ID 的 submit_sm_resp。稍后短信中心发来 deliver_sm，里面是送达回执。应用用 deliver_sm_resp 确认。工作结束后发送 unbind，关闭会话。

| Item | Value | Note |
| --- | --- | --- |
| 状态一 · 1 | 应用（ESME） |  |
| 状态一 · 2 | bind_transceiver | 建立会话 |
| 状态一 · 3 | SMSC |  |
| 状态一 · 4 | submit_sm_resp | 已受理 |
| 状态一 · 5 | 送达回执 |  |

Source: smpp.org：SMPP 会话与 PDU 操作 (https://smpp.org/)

## 窗口就是约定

窗口是客户端在等待响应之前可以同时在途的请求数。它不是建议值。发得比窗口多，短信中心就限流。限流后还按原速率重试，队列只会越积越长。每次提交都要读响应码，遇到限流就降速，等窗口排空再发下一波。
心跳用来确认会话还活着。从不发 enquire_link 的客户端，可能一直挂在一条已经死掉的连接上，直到第一次提交失败才发现。每次掉线都立刻重连的客户端，又会压垮服务商。要退避重连、限制重连频率，并在绑定中断超过业务可承受时间时告警。

### 一条 PDU，逐字段拆开

头部固定，报文体随命令而变。submit_sm 带地址、编码和回执标志。

Alt: 一条解码后的 submit_sm PDU，显示命令长度、命令 ID、状态、序列号和报文体字段。

每条 PDU 都以四字节命令长度、四字节命令 ID、四字节命令状态和四字节序列号开头，后面是报文体。submit_sm 的报文体包括源地址、目的地址、短消息、数据编码和回执标志。可选参数以标签-长度-值字段传送。

| Item | Value | Note |
| --- | --- | --- |
| command_length | 53 |  |
| command_id | 0x00000004 |  |
| command_status | 0x00000000 |  |
| sequence_number | 1 |  |
| service_type |  |  |
| source_addr_ton | 1 |  |
| source_addr_npi | 1 |  |
| source_addr | 12345 |  |
| dest_addr_ton | 1 |  |
| dest_addr_npi | 1 |  |
| destination_addr | 15551234567 |  |
| esm_class | 0x00 |  |
| protocol_id | 0x00 |  |
| priority_flag | 0 |  |
| schedule_delivery_time |  |  |
| validity_period |  |  |
| registered_delivery | 0x01 |  |
| replace_if_present_flag | 0x00 |  |
| data_coding | 0x00 |  |
| sm_default_msg_id | 0x00 |  |
| sm_length | 4 |  |
| short_message | 54657374 |  |
| 文本 | Test |  |

Source: SMPP v3.4 规范：PDU 头部与 submit_sm (https://smpp.org/SMPP_v3_4_Issue1_2.pdf)

## 一条短信的一天

客户端打开收发绑定，读取绑定响应。它提交一条短信，把响应里的 message ID 存下来。短信中心把短信路由到目的网络。几分钟后，一条 deliver_sm 带回回执：原始 message ID、状态，往往还有网络错误码。客户端确认回执，把状态和自己的记录对上。
每一步都有失败方式。凭据不对或接口版本不对，绑定会被拒。提交可能被限流、被拒绝，也可能先受理、后面在回执里失败。回执可能在验证码过期之后才到。客户端要存 message ID，能接受迟到的回执，并把应用自己的状态当作“用户做了什么”的准绳。

解码器在浏览器里运行，粘贴的回执不会离开本页。

[Open the tool](/zh/tools/smpp-decoder/?src=learn-what-is-smpp&scenario=dlr-example&sample=id%3A0123456789+sub%3A001+dlvrd%3A001+submit+date%3A2610181200+done+date%3A2610181201+stat%3ADELIVRD+err%3A000+text%3A%E6%82%A8%E7%9A%84%E9%AA%8C%E8%AF%81%E7%A0%81%E6%98%AF+123456)

### 先解码回执，再怀疑路由

把一条送达回执粘进 [SMPP 与 DLR 解码器](/zh/tools/smpp-decoder/)，逐字段读。看 message ID、状态、完成时间和错误码。状态不是 DELIVRD 时，错误码要对照服务商的代码表来读，可据此判断是号码、手机还是网络拒绝了这条短信。先做这一步，再让服务商改路由。

## 回执与排障

回执是异步的，以 deliver_sm PDU 的形式回到会话上，格式取决于短信中心。较新的实现把状态放在 message_state 这个标签-长度-值字段里。较旧的实现把文本回执放进短消息字段，用 id、stat、err 这样的键值对表示。两种都要能解析，不能只认一种。
按 message ID 匹配，不要按到达顺序。相隔一秒提交的两条短信，回执可能倒着回来，重试还可能产生重复。提交时存下 ID，回执到达时更新记录。同一个 ID 的第二条回执只有状态更新时才采纳。[接入指南](/zh/resources/guides/smpp-http-connection/)把这套做法写成了一份操作顺序。

### Check what you learned

**为什么再加一条绑定，比提高重试速率更有用？**

一条绑定只有一个窗口。加绑定是加容量，对着满窗口重试，只会增加排队和延迟。

**message ID 从哪里来？**

短信中心在 submit_sm_resp 里返回。存下它，之后按这个 ID 匹配回执。

**“已送达”的回执能证明什么？**

证明网络已接受并把短信送到手机方向，不证明有人读过。

## FAQ

**刚开始就必须用 SMPP 吗？**

不必。HTTP 一个下午就能接好。流量稳定到值得维护一条会话时，SMPP 才划算。

**什么是绑定？**

一条持续打开的会话，加上声明的方向：发送、接收或收发。它承载吞吐配额，靠心跳保持打开。

**什么是 PDU？**

协议数据单元，SMPP 交换的二进制消息。每条 PDU 有 16 字节头部，报文体随命令而变。

**可以走公网用 SMPP 吗？**

通常可以，配合 TLS 和 IP 白名单，但要问服务商。有些部署会用专线。

**长短信怎么处理？**

可以用带用户数据头的拼接分段，也可以用网络负责分段的 payload TLV。最终要在手机上验证。

## Sources

- [smpp.org：SMPP 会话、绑定操作与送达回执](https://smpp.org/) — Accessed: 2026-10-19
- [SMPP v3.4 规范，Issue 1.2](https://smpp.org/SMPP_v3_4_Issue1_2.pdf) — Accessed: 2026-10-19
- [3GPP TS 23.040：短消息业务的技术实现](https://www.3gpp.org/ftp/Specs/archive/23_series/23.040/) — Accessed: 2026-10-19

Updated: 2026-10-19