熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

在CMPP2.0 協議SP端的.NET開發

2022-06-13   來源: Java核心技術 

  CMPP協議簡介
  中國移動通信互聯網短信網關接口協議(China Mobile Peer to Peer CMPP)是中國移動夢網內部各SMS參與節點相互交換SMS的官方協議作為夢網的參與方移動夢網的增值服務商(Service Provider SP )要按照此協議規范實現SP的部分才可以將自己的短信通過移動的GSM網絡的數據通道傳輸到最終手機用戶上
  
  實際上協議規范了個方面的內容
  
  SP與移動的互聯網短信網關(Internet Short Message GatewayISMG)之間的接口協議
  
  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 OriginateSMMO)短信發送短信從手機用戶端發送到目標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端的消息發送給ISMGISMG將返回一個MSGID給SP標示此消息之後(小時以內但一般最多幾分鐘內就可)ISMG返回關於此消息的遞送報告遞送報告同MO短消息是通過另外一個重要消息CMPP_DELIVER來提交給SP的
  
  CMPP_DELIVER的各個字段
   
  如果是報告那麼Msg_Content將按照狀態報告結構來解釋
   
  關於State字段如下解釋
  
  安全驗證
  
  CMPP協議在CMPP_CONNECT中傳遞驗證消息驗證消息為字節的+移動給出的密碼+當前時間戳字節數組的MD算法後的字節時間戳為 月日時分秒代碼算法如下
  
  private byte[] getMdCode()
  
  {
  
  byte[] buf=new byte[++_PasswordLength+] ;
  
  byte[] s_a=EncodingASCIIGetBytes(_SystemID); //就是企業代碼
  
  byte[] s_={};   //字節的此處當作右補
  
  byte[] s_p=EncodingASCIIGetBytes(_Password); //密碼
  
  this_timestamp =getTimestamp();  //取得認證碼時賦值字符串
  
  byte[] s_t=EncodingASCIIGetBytes(_timestamp); //位字符串字節數組
  
  s_aCopyTo(buf);
  
  s_CopyTo(buf);
  
  s_pCopyTo(buf+);
  
  s_tCopyTo(buf++_PasswordLength);
  
  MD md= new MDCryptoServiceProvider(); //創建MD類別
  
  return(mdComputeHash(bufbufLength));
  
  }
  
  其中getTimestamp函數為返回例如秒)這樣的字符串詳細代碼略過有興趣請查看本文的附件代碼
  
  廠商API問題
  
  筆者公司所處廣東廣東移動提供了華為的以C 形式的API(SMEIDLLdll)來幫助大家初期熟悉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編碼所以全部可以采用SystemTextEncodingASCII進行編碼和解碼對於Msg_Content字段由於一般情況下存在漢字信息傳輸所以默認的編/解碼應該為EncodingDefault實際是什麼編碼還要考察MSG_Fmt字
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26012.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.