长短信实现系列之移动CMPP2.0

1)背景
目前我们的短信发送基本上就是超过140字节(甚至更少)就切分(移动普通短信超过140个字节甚至都发送不了,联通倒是可以),然后分几条发给客户,而且也不能保证顺序,用户体验不好,
运营这边抱怨说精简再精简还是超过了字数,于是长短信的支持就成为必须的事情了。

2)原理


2.1)长短信的协议和普通短信的协议稍有不同


2.1.1) TP_udhi=1
在Msg_content中加入6个字节或者7个字节的udhi头做为前缀

2.1.2)6个字节的TP_udhi协议头
05 00 03 XX MM NN
byte 1 : 05, 表示剩余协议头的长度
byte 2 : 00, 这个值在GSM 03.40规范9.2.3.24.1中规定,表示随后的这批超长短信的标识位长度为1(格式中的XX值)。
byte 3 : 03, 这个值表示剩下短信标识的长度
byte 4 : XX,这批短信的唯一标志,事实上,SME(手机或者SP)把消息合并完之后,就重新记录,所以这个标志是否唯一并不是很 重要。
byte 5 : MM, 这批短信的数量。如果一个超长短信总共5条,这里的值就是5。
byte 6 : NN, 这批短信的数量。如果当前短信是这批短信中的第一条的值是1,第二条的值是2。
例如:05 00 03 39 02 01

2.1.3)7个字节的TP_udhi协议头
06 08 04 XX XX MM NN
byte 1 : 06, 表示剩余协议头的长度
byte 2 : 08, 这个值在GSM 03.40规范9.2.3.24.1中规定,表示随后的这批超长短信的标识位长度为2(格式中的XX值)。
byte 3 : 04, 这个值表示剩下短信标识的长度
byte 4-5 : XX XX,这批短信的唯一标志,事实上,SME(手机或者SP)把消息合并完之后,就重新记录,所以这个标志是否唯 一并不是很重要。
byte 6 : MM, 这批短信的数量。如果一个超长短信总共5条,这里的值就是5。
byte 7 : NN, 这批短信的数量。如果当前短信是这批短信中的第一条的值是1,第二条的值是2。
例如:06 08 04 00 39 02 01

2.2)实现方式
我们的短信网关还是要按140个字节切分短信,只是短信的字节和以前稍有不同(见2.1的说明),短信中心通过把切分的短信发送到手机终端,
手机终端根据udhi协议头再把这几条短信组合成一条完整的短信显示在手机屏幕

3)action


3.0)简略的下行流程
我们的网关程序(SP)<-------CMPP2.0协议----->互联网短信网关(ISMG)<-----SMPP协议--------->短消息中心(SMC)<-----无线协议---->手机终端


3.1)第一阶段
条件:(6字节协议头,TP_udhi=1, Pk_total Pk_number均为1或者0或者和TP_udhi头一致,Msg_Fmt为Gbk)
终端无法收到,从短信中心获得错误码 MA:0054,意思是短信中心不返回行业网关响应消息

条件:(7字节协议头,TP_udhi=1, Pk_total Pk_number均为1或者0或者和TP_udhi头一致,Msg_Fmt为Gbk)
终端无法收到,从短信中心获得错误码MB : 1057,意思是短信中心返回行业网关错误响应消息

具体错误原因,如何改正,我问过移动技术人员,没有结果

3.2)第二阶段
突发奇想,把Msg_Fmt改为ucs2,即设为8而不是15,情况发生了变化
条件:(6字节协议头,TP_udhi=1, Pk_total Pk_number均为1或者0或者和TP_udhi头一致,Msg_Fmt为ucs2)
能收到一条
另外一条行业网关就出问题,返回错误代码为8,表示流量过大

条件:(7字节协议头,TP_udhi=1, Pk_total Pk_number均为1或者0或者和TP_udhi头一致,Msg_Fmt为ucs2)
能收到一条
另外一条行业网关就出问题,返回错误代码为8,表示流量过大

后来才发现这个错误是自己造成的,我设了msg fmt,但Msg_content中的字节确还是原来的gbk的

3.3)第三阶段
改正了上面的错误之后,居然ok了
此时的情况是:
(7字节,TP_udhi=1, Pk_total Pk_number和udhi头一致,msg fmt为ucs2)

3.4) 举个例子
我要发送AAABBBCCC,我拆成3条:AAA, BBB, CCC
3条分别如下
AAA :
Pk_total: 03
Pk_number: 01
TP_udhi: 01
Msg_Fmt: 08
Msg_Content: 06 08 04 00 39 03 01 00 41 00 41 00 41

BBB :
Pk_total: 03
Pk_number: 02
TP_udhi: 01
Msg_Fmt: 08
Msg_Content: 06 08 04 00 39 03 02 00 42 00 42 00 42

CCC :
Pk_total: 03
Pk_number: 03
TP_udhi: 01
Msg_Fmt: 08
Msg_Content: 06 08 04 00 39 03 03 00 43 00 43 00 43

注意TP_udhi 的协议头中的XX XX 在这里为 00 39  是我随机产生的。


4)结论

  • 必须设置TP_udhi为1
  • 必须在Msg_contetnt前加入TP_udhi协议头,协议头我目前使用的是7字节的,我认为6字节应该也可以,你可以试下
  • Pk_total,Pk_number是否一定设置的和TP_udhi协议头中的MM NN 一致,我目前是一致,但我觉得不一致也可以,就像普通短信中这个字段都为1,你可以试下
  • Msg_Fmt一定不能选择15即gbk,我目前选的是8(UCS2),其他的行不行,你可以试下
  • 感觉到7字节还是有好处的,特别是用了两个字节XX XX 来标示一批短信,如果这两个字节随机产生(如果不随机产生,实现成本要大很多),这使得在大并发的情况下,冲突(某时刻某个手机接到的两批短信批次相同会导致手机合并短信出问题)的可能性下降了很多。
  • 最好能有个模拟网关测试下,虽然模拟仅模拟行业网关,但至少能避免我第二阶段发生的愚蠢的错误,最好还能有个tcpdump工具,来检测发送的字节是否正确。
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页