c#

位置:IT落伍者 >> c# >> 浏览文章

在CMPP2.0 协议SP端的.NET开发


发布日期:2018年05月10日
 
在CMPP2.0 协议SP端的.NET开发

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字               

上一篇:代码最优化.NET中的内存管理

下一篇:基于.NET架构的核