一CMPP協議簡介 中國移動通信互聯網短信網關接口協議(China Mobile Peer to Peer CMPP)
是中國移動夢網內部各SMS參與節點相互交換SMS的官方協議
作為夢網的參與方
移動夢網的增值服務商(Service Provider SP )要按照此協議規范實現SP的部分
才可以將自己的短信通過移動的GSM網絡的數據通道傳輸到最終手機用戶上
實際上
協議規范了
個方面的內容
SP與移動的互聯網短信網關(Internet Short Message Gateway
ISMG)之間的接口協議
ISMG之間的接口協議(譬如移動各省
市之間的短信息交換通過ISMG之間進行)
ISMG與匯接網關(Gateway Name Server GNS
類似互聯網上的DNS服務器)之間的接口協議
譬如跨省之類的短信需要GNS的幫助指出當前ISMG該如何傳遞短信
其中
後二方面屬於移動短信息系統內部實現
對於SP來講大概可以
透明
來看待
只要實現了SP同ISMG的正確交互
就可以實現接入移動夢網短信系統
我們關心的只是SP端的開發細節
二CMPP交互模式 從手機用戶角度講
按短信的發起/接收路徑來講
有兩個叫法
MT(Short Message Mobile Terminated
SMMT)
短信接收
短信從SP發送到手機用戶
MO (Short Message Mobile Originate
SMMO)
短信發送
短信從手機用戶端發送到目標SP
這兩類短信交互
從SP端來看
都是屬於Socket傳輸應用
CMPP的協議是以TCP/IP協議作為底層承載協議的
屬於TCP/IP協議棧之上的應用
SP同ISMG的交互連接分長連接和短連接
所謂短連接
就是一次連接
傳輸一個消息
然後等待回復後拆除連接
顯然
效率很低
所以
基本上不被考慮(實際應用移動也不允許SP采用短連接
只是不明白移動為什麼還要寫入文檔? ISMG間會需要?)
所謂長連接
就是SP建立同ISMG連接
然後不斷將數據包(一個個CMPP消息)發送到ISMG
此處發送不必等待某條消息的ISMG回應消息返回
就接著發送下一個消息
同時
等待ISMG返回信息或者等待ISMG發送給SP的消息
發送同接收消息不是一定要同步的
實際采用異步(同時也時雙工)模式
從效率上
顯然
必須全雙工的異步模式才能夠滿足實際應用需求
三SP端開發 消息分類
首先
圖中的CMPP消息有很多種
SP同ISMG之間交流這些消息
大體上這些消息發出後
對方往往需要回復一個應答(RESP)類消息
注意
這些消息大多具有方向性
也就是說只能夠從一端到另一端
而不可反方向進行
有些(少數)則可兩端都能夠發出
以下信息主要來源於移動的文檔
但針對大家易混淆或源文檔解釋不夠詳細做了明確和補充
具體見下表
交互階段
整個CMPP協議交互分為驗證
事務兩個階段
驗證階段
發送CMPP_CONNECTION消息進行驗證
通過驗證後(必須要通過才)進入CMPP事務階段
可以發送短信數據了
上表中的CMPP_CONNECTION以下的消息都屬於事務階段的消息
消息數據結構
每一個消息包含 消息頭 和 消息體兩個部分
頭固定長度為
字節
其他消息長度各異
但是同一類型消息的長度是固定的
所有消息的各個字段基本上僅有
種類型
Unsigned Integer (無符號整型)
Integer(整型)
Octet String(字符串)
每種類型具體長度不定
網絡字節順序
消息頭(
個Unsigned Integer字段組成)
字節的Total_Length (Unsigned Integer)
包含了此消息的總計(包括了頭部分)長度
字節的Command_Id(Unsigned Integer)
指明了此消息到底是什麼消息
就是上表中消息的枚舉值
應用程序根據此值確定本數據包到底是什麼消息
從而可以按照確定的消息類型
解析余下的消息體
字節的Sequence_Id(Unsigned Integer)
指明了此數據包在發送此消息端的唯一編號
這個唯一編號
實際上可以看作流水操作編號
因為分析到交互模式我們看到
SP發送數據到ISMG
不是每發送一個就停下來等待ISMG的回復
而是
一下子
發送多個數據包過去
然後等待ISMG的回應
然而
怎麼知道回應的消息是到底對應之前發送過去的消息中的那一條呢?本字段就是解決此難題
SP按照編號發送消息過去
等待ISMG的回應—一般情形下回應消息數據結構都有表明本消息回應的是SP發出的哪一條消息
這個對應就是依靠Sequence_Id
它並不要求一定要嚴格唯一
但是在給定的一段時間內
必須唯一(基本上只要SP發送過去的消息中沒有重復就行了)
如果是需要SP回答的消息
SP也必須將ISMG發送過來的消息的Sequence_Id填入相應字段
表明這是某個消息的回應
SP端和ISMG端Sequence_ID都沒有確定具體的算法
SP可以(但不推薦)采用數據庫的唯一Id作為此值
消息體
消息體長度根據消息不同
長度不一
其他的參考移動的文檔《中國移動通信互聯網短信網關接口協議(China Mobile Peer to Peer
CMPP)(V
)》
這裡著重講講
個重要消息的消息體數據結構
CMPP
_SUBMIT的消息體
CMPP_SUBMIT消息長度是可變的
將SP端的消息發送給ISMG
ISMG將返回一個MSGID給SP標示此消息
之後(
小時以內
但一般最多幾分鐘內就可)
ISMG返回關於此消息的遞送報告
遞送報告同MO短消息是通過另外一個重要消息CMPP
_DELIVER來提交給SP的
CMPP
_DELIVER的各個字段
如果是報告
那麼Msg_Content將按照狀態報告結構來解釋
關於State字段
如下解釋
安全驗證
CMPP協議在CMPP_CONNECT中傳遞驗證消息
驗證消息為
字節的
+移動給出的密碼+當前時間戳字節數組的MD
算法後的字節
時間戳為 月日時分秒
位
代碼算法如下
private byte[] getMd
Code()
{
byte[] buf=new byte[
+
+_Password
Length+
] ;
byte[] s_a=Encoding
ASCII
GetBytes(_SystemID); //就是企業代碼
byte[] s_
={
}; //
字節的
此處當作右補
byte[] s_p=Encoding
ASCII
GetBytes(_Password); //密碼
this
_timestamp =getTimestamp(); //取得認證碼時賦值字符串
byte[] s_t=Encoding
ASCII
GetBytes(_timestamp); //
位字符串字節數組
s_a
CopyTo(buf
);
s_
CopyTo(buf
);
s_p
CopyTo(buf
+
);
s_t
CopyTo(buf
+
+_Password
Length);
MD
md
= new MD
CryptoServiceProvider(); //創建MD
類別
return(md
ComputeHash(buf
buf
Length));
}
其中getTimestamp函數為返回例如
(
月
號
點
分
秒)這樣的字符串
詳細代碼略過
有興趣請查看本文的附件代碼
廠商API問題
筆者公司所處廣東
廣東移動提供了華為的以C 形式的API(SMEIDLL
dll)
來幫助大家初期熟悉CMPP協議
但是
經過開發測試
發現華為的API至少存在幾個問題
封裝成幾個API函數
但是由於CMPP自身的復雜性
導致這些函數丑陋無比
參數多
而且難以明晰含義
華為的API
內部將CMPP的驗證
事務階段分成幾個函數實現
其中將發送SMS到ISMG功能以函數提供
竟然出現SubmitAExExEx之類的函數說明
CMPP的交互是異步的
需要多線程實現一邊發送
一邊接收反饋信息
此API應當是內部維護一個線程進行CMPP_SUBMIT消息發送
但是華為API卻通過空循環之類的操作等待ISMG返回CMPP_SUBMIT_RESP得到相應的MSGID再返回(從而實現消息同步返回)
經過測試
大約需要
毫秒
這個在實際SP的高性能需求場合根本無法滿足系統要求
接收短信必須依靠程序主動先發出函數HasDeliverMessage調用
得到有消息才可通過GetDeliverSMEx函數獲取消息
顯然
這種方式是低效率的
而且容易產生消息數據包丟失
表現為有些MO消息
SP接收不到
而且
令人疑惑的是
你還不能夠新開一個線程專門來做判斷並接收MO的動作
實際開發中一旦采用線程來做就回發生內存保護錯誤(大概屬於同API自身的線程有沖突)
返回錯誤碼
往往又是華為自己定的一套錯誤碼(大概華為設計此API為了適應SMGP CMPP等多個協議)
而且經常變動
很是傷腦筋
基於以上理由
我認為自己按照CMPP協議開發一個SP端程序
比較能夠滿足一般SP的需求
四C#實現 CMPP協議實現類CMPPClient
通過研究
筆者用C#寫了一組類實現自己的CMPP SP端程序(CMPPClient)
為了實現相關類
還需要編寫一些輔助類
並且首先要解決CMPP協議的數據結構同C#的數據之間的轉換問題
CMPP的Octet String 實際上相當於C#中的byte[]
所有CMPP消息的Octet String字段出了CMPP_SUBMIT和CMPP_DELIVER的msg_content字段外
其他的都可以認為是ASCII編碼
所以全部可以采用System
Text
Encoding
ASCII進行編碼和解碼
對於Msg_Content字段
由於一般情況下存在漢字信息傳輸
所以默認的編/解碼應該為Encoding
Default
實際是什麼編碼還要考察MSG_Fmt字
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26012.html