長短信實現系列之移動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工具,來檢測發送的字節是否正確。
發佈了200 篇原創文章 · 獲贊 7 · 訪問量 106萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章