当前位置:文档之家› CMPP2API用户使用手册

CMPP2API用户使用手册

CMPP2API用户使用手册

北京风起水流软件工作室

范圣刚

网址:https://www.doczj.com/doc/716234737.html,

电邮:princetoad@https://www.doczj.com/doc/716234737.html,

手机:(010)139********

V1.0 2007‐5‐11

https://www.doczj.com/doc/716234737.html, 1

目录

一、 简介 (5)

1. 什么是SMAL? (5)

2. SMAL目前支持哪些协议? (5)

二、 CMPP2API目录说明和文件列表 (6)

1. ./include (6)

./include/smal.h (6)

./include/common (6)

./include/cmpp2 (6)

2. ./lib (7)

./lib/zealware_cmpp2.lib (7)

./lib/zealware_cmpp2d.lib (7)

3. ./doc (7)

4. ./cmpp2apidemo (7)

三、 CMPP2API的功能特点 (8)

四、 使用CMPP2API开发短消息网关程序 (9)

1. CMPPClient类的使用 (9)

2. CMPPClient的主要功能函数 (9)

Initialize (9)

MakeConnection (10)

Release (16)

Submit (17)

3. CMPPClient的消息和事件处理函数 (20)

OnConnectionLogined (20)

https://www.doczj.com/doc/716234737.html, 2

OnConnectionLoginFailed (20)

OnConnectionCleared (21)

OnConnectionSubmiting (21)

OnConnectionSubmited (22)

OnConnectionSubmitFailed (22)

OnReceivedConnectionConnectResponse (23)

OnReceivedConnectionTerminate (23)

OnReceivedConnectionSubmitResponse (24)

OnReceivedConnectionDeliver (24)

OnReceivedConnectionStatusReport (25)

OnReceivedConnectionQueryResponse (25)

OnReceivedConnectionCancelResponse (26)

OnReceivedConnectionActiveTest (26)

OnReceivedConnectionActiveTestResponse (27)

OnConnectionLogWrite (27)

4. 消息数量统计函数 (29)

GetSubmitCount (29)

GetSubmitSucceedCount (29)

GetSubmitFailedCount (29)

GetRespFailedCount (30)

GetRespSucceedCount (30)

GetDeliverCount (30)

GetStatusReportCount (31)

5. 使用CMPP2API接口库一步一步开发一个短信网关程序 (32)

https://www.doczj.com/doc/716234737.html, 3

1) 新建一个Win32控制台项目,名称”CMPP2SMG”。 (32)

2) 在”应用程序设置”里面添加”MFC支持”。 (33)

3) 将CMPP2API的include目录和lib目录分别添加到Visual stuio的系统目录

中。 (33)

4) 在头文件”CMPP2SMG.h”中包含CMPP2API接口库的头文件和库文件。 . 34

5) 从CMPPClient派生一个自己的类MyCMPPClient用来处理短信操作。 (34)

6) 在CMPP2SMG.cpp中撰写具体的MyCMPPClient实现,主要功能是将收到

的消息内容打印到命令行窗口。 (37)

7) 声明并定义一个MyCMPPClient实例,在_tmain函数中执行

Initialize,MakeConnection,Submit,和Release调用,这样一个完整的网关程序就

完成了! (43)

6. CMPP2API对不同网关厂商差异的适应 (46)

五、 附录 (47)

1. CMPP_SUBMIT定义 (47)

2. 接口库错误码表 (53)

六、 参考 (54)

https://www.doczj.com/doc/716234737.html, 4

一、简介

CMPP2API短消息网关开发接口库是由北京风起水流软件工作室

(https://www.doczj.com/doc/716234737.html,)开发的SMAL开发库的一部分,支持中国移动的CMPP2.0协议。

1.什么是SMAL?

SMAL是short message abstract library的缩写,是一个主要用于短信网关平台的底层抽象接口库,通过对短信协议的抽象封装,可以在smal上面方便地实现CMPP,SGIP,SMPP,SMGP,CNGP,EMPP等短信协议,同时可以很方便地在上面扩展实现新的协议和自定义的内部协议等。

2.SMAL目前支持哪些协议?

SMAL目前支持的协议包括中国移动的CMPP2.0,CMPP3.0,中国联通的 SGIP1.2, SGIP1.2修订版,中国电信的SMGP2.0,SMGP3.0,中国网通的CNGP2.0,和国际标准SMPP3.3,SMPP3.4,以及企信通协议EMPP等。

https://www.doczj.com/doc/716234737.html, 5

二、CMPP2API目录说明和文件列表

1../include

接口库的包含文件目录,里面是接口库所需的头文件

./include/smal.h

包含windows和MFC的一些文件和定义,所有的SMAL库都需要用到该文件。

./include/common

SMAL库的各个协议的通用头文件所在目录

./include/common/buffer.h

处理消息字段和消息内容的类

./include/common/const.h

接口库的所有常量定义,例如命令字,错误代码等。

./include/common/logqueue.h

日志队列类

./include/common/md5.h

MD5算法头文件

./include/common/tcpsocket.h

TCP网络通讯类

./include/common/threadpool.h

线程池类

./include/common/util.h

一些功能函数和类定义

./include/cmpp2

SMAL库中CMPP2协议需要的头文件所在目录

./include/cmpp2/cmpp_message.h

定义了CMPP消息结构。

./include/cmpp2/cmppbase.h

定义了CMPP底层函数操作

./include/cmpp2/cmppconn.h

定义了CMPP连接和CMPP端点类。

https://www.doczj.com/doc/716234737.html, 6

2../lib

静态库文件目录

./lib/zealware_cmpp2.lib

Release版的cmpp2lib库文件

./lib/zealware_cmpp2d.lib

debug版的cmpp2lib库文件

3../doc

相关文档目录

4../cmpp2apidemo

VC7.1示例工程目录,演示了如何用CMPP2API很容易地开发一个完整的SP网关程序。

https://www.doczj.com/doc/716234737.html, 7

三、CMPP2API的功能特点

z运行稳定。经过五年在线运行,目前在全国有超过100家SP采用我们提供的CMPP2API接口库。

z效率高,资源占用率低。CMPP2API内建线程池和中间件系统,采用多连接,多线程的WINDOWS完成端口技术,采用智能路由和连接分配方法,能够处理大量的并发短信,最充分地利用系统资源。线程池能够根据当前的系统负荷,动态地进行线程数调节,动态地增减线程。

z网关完全符合CMPP2.0协议标准。支持各省和全网的所有移动网关,同时兼容亚信,华为,东软,清华深讯,思特奇等所有网关厂商平台。

z高度封装,开发效率高。二次开发人员只需要很少的开发工作就可以实现短信网关应用和业务开发。

z支持自动重连,活动检测,超长短信的功能。参数定制性强,可以同时连接多个网关进行消息收发。

https://www.doczj.com/doc/716234737.html, 8

四、使用CMPP2API开发短消息网关程序

CMPP2API接口库定义了CMPPClient类来处理网关操作,包括创建连接,收发消息和处理消息响应等,使用CMPPConnection类来描述一个网关连接,每个CMPPConnection类可以有自己的网关地址,端口号,用户名,口令,企业代码和特服号等属性。

每个CMPPClient类可以管理最多255个CMPPConnection成员,也就是可以同时建立255个网络连接,从而实现了同时连接多个不同网关的功能。

1.CMPPClient类的使用

CMPPClient类提供了初始化函数Initialize来初始化系统线程池,提供了MakeConnection 函数来建立同网关的连接,提供了Submit函数向网关提交消息,同时提供了一系列的事件回调函数对cmpp命令字和状态进行回调处理,如OnConnectionLogined(成功登录网关时调用),OnReceivedConnectionDeliver(收到Deliver消息时调用)。

因此,使用CMPP2API时,只需从CMPPClient继承自己的类,调用Initialize()初始化线程池,调用MakeConnection()建立同网关的连接,调用Submit()发送下行消息,然后重写要实现的消息和事件回调函数就可以了。

2.CMPPClient的主要功能函数

Initialize

Initialize函数用来对CMPPClient中的内建线程池进行初始化,指定线程池要使用的初始线程数和允许使用的最大线程数。

void Initialize(

unsigned nMinWorkThreadsCount = 4,

unsigned nMaxWorkThreadsCount = 8

);

参数

nMinWorkThreadsCount

[输入参数]指定线程池要使用的初始线程数(也就是最小线程数),如果在消

息和事件处理函数中没有复杂的耗时较长的操作,初始线程数的最合理值=CPU

个数*2+2;如果需要在消息和事件处理函数中执行耗时较长的操作(如数据库

操作),则最好将初始线程数设置地大一些,如50或100。

https://www.doczj.com/doc/716234737.html, 9

nMaxWorkThreadsCount

[输入参数]指定线程池允许使用的最大线程数。线程池可以根据工作负载动态

调整工作线程数,在负荷减少时,减少工作线程数;在负荷增加时,增加工作

线程数,但是最多不会超过这里指定的最大线程数,以免影响系统整体和其他

应用程序的工作。

返回值

注意

最大线程数应该大于初始线程数。系统内部设定了一个静态线程数变量

nStaticThreads,值等于CPU个数*2+2,是内置线程池的最低线程数。同时系统还设定了一个最大线程数变量MAXWORKTHREADS,值等于256。输入参数

nMinWorkThreadsCount和nMaxWorkThreadsCount的值都应该位于nStaticThreads 和MAXWORKTHREADS之间,否则系统会自动纠正。如果输入参数

nMinWorkThreadsCount小于nStaticThreads,nMinWorkThreadsCount会被改写成nStaticThreads;如果输入参数nMinWorkThreadsCount大于MAXWORKTHREADS,nMinWorkThreadsCount的值会被改写成MAXWORKTHREADS。

每个CMPPClient对象在进行所有操作之前必须调用Initialize()进行初始化操作。

示例代码

MyCMPPClient * client;

client‐>Initialize(4, 10);

MakeConnection

建立一个同网关的连接。

当调用MakeConnection函数时,接口库将建立一个同指定网关地址和端口的TCP 连接CMPPConnection,同时根据输入参数(用户名,口令,企业代码,连接类型)构建并发送CMPP_CONNECT登录包,然后接收网关回复的登录应答包

CMPP_CONNECT_RESP。

CMPPConnection * MakeConnection(

const CString & _smghost,

https://www.doczj.com/doc/716234737.html, 10

const unsigned short & _smgport,

const unsigned char & _smgversion,

const CString & _username,

const CString & _password,

const CString & _icpid,

const ConnectionType & _conntype,

const BOOL & _isAsiaInfoSmg,

const int & _nActivetestInterval,

BOOL sync

);

参数

smghost

[输入参数]要连接的网关地址。

_smgport

[输入参数]要连接的网关端口号。

_username

[输入参数]登录网关的用户名。

_password

[输入参数]登录口令。

_icpid

[输入参数]企业代码。

_conntype

[输入参数]连接类型。连接类型分为接收连接(e_RecvOnly),发送连接

(e_SendOnly),收发连接(e_SendAndRecv)。

_isAsiaInfoSmg

https://www.doczj.com/doc/716234737.html, 11

[输入参数]是否是亚信网关。

_nActivetestInterval

[输入参数]活动测试时间间隔。在CMPP里面,网关要求的活动测试时间间隔一般是30秒,考虑到网络延迟,系统延迟等因素,这里我们最好将其设置为小于29秒,如25秒。

sync

[输入参数]是否同时登录网关(一般填TRUE)。如果设为FALSE的话,接口库将只建立到网关的TCP连接,而不发送登录包。

返回值

如果成功连接的话,返回一个指向刚刚建立成功的CMPPConnection连接的指针,否则返回NULL。

注意

MakeConnection中使用的参数,大都是需要运营商(中国移动)提供的参数,例如网关地址、端口号、登录用户名、密码和企业代码。还需要向运营商确认的是网关厂商,即要连接的移动网关是由哪家网关厂商提供的。

MakeConnection调用成功的话,会创建一个新的CMPPConnection对象,即一个新的网关连接。每一个网关连接(CMPPConnection对象)由一个字符串token唯一标识,可以通过调用CMPPConnection对象的GetToken函数获得。

示例代码

// 发送连接是否成功建立

BOOL fMTConnected = FALSE;

// 接收连接是否成功建立

BOOL fMOConnected = FALSE;

// 收发连接是否成功建立

BOOL fMTAndMOConnected = FALSE;

// 建立发送连接

https://www.doczj.com/doc/716234737.html, 12

if (!m_fGWConnected) {

int ix = 0;

fMTConnected = TRUE;

for (ix = 0; ix < (int)m_bMTConnections; ix++) {

CMPPConnection * connection = client‐>MakeConnection(

m_sSmgHost,

(const unsigned short)m_ushMTPort,

(const unsigned char)CMPP2_VERSION,

(const CString)m_sLoginName,

(const CString)m_sLoginPwd,

(const CString)m_sICPID,

e_SendOnly,

(const BOOL)m_fAsiaInfoSMG,

(const int)9,

TRUE

);

if (connection == NULL || !connection‐>IsOpened() ) {

ShowLog("INFO|建立第%d个发送连接失败", ix+1);

fMTConnected = FALSE;

break;

}

else {

ShowLog("INFO|建立第%d个发送连接成功", ix+1);

https://www.doczj.com/doc/716234737.html, 13

}

}

// 建立接收连接

if (fMTConnected) {

int iy = 0;

fMOConnected = TRUE;

for (iy = 0; iy < m_bMOConnections; iy++) {

CMPPConnection * connection = client‐>MakeConnection(

m_sSmgHost,

(const unsigned short)m_ushMOPort,

(const unsigned char)CMPP2_VERSION,

(const CString)m_sLoginName,

(const CString)m_sLoginPwd,

(const CString)m_sICPID,

e_RecvOnly,

(const BOOL)m_fAsiaInfoSMG,

(const int)9,

TRUE

);

if (connection == NULL || !connection‐>IsOpened() ) {

ShowLog("INFO|建立第%d个接收连接失败", iy+1);

fMOConnected = FALSE;

https://www.doczj.com/doc/716234737.html, 14

break;

}

else {

ShowLog("INFO|建立第%d个接收连接成功", iy+1);

}

}

}

// 建立收发连接

if (fMTConnected && fMOConnected) {

int iz = 0;

fMTAndMOConnected = TRUE;

for (iz = 0; iz < m_bMTAndMOConnections; iz++) {

CMPPConnection * connection = client‐>MakeConnection(

m_sSmgHost,

(const unsigned short)m_ushMTAndMOPort,

(const unsigned char)CMPP2_VERSION,

(const CString)m_sLoginName,

(const CString)m_sLoginPwd,

(const CString)m_sICPID,

e_SendAndRecv,

(const BOOL)m_fAsiaInfoSMG,

(const int)9,

TRUE

https://www.doczj.com/doc/716234737.html, 15

);

if (connection == NULL || !connection‐>IsOpened() ) {

ShowLog("ERROR|建立第%d个收发连接失败", iz+1);

fMTAndMOConnected = FALSE;

break;

}

else {

ShowLog("INFO|建立第%d个收发连接成功", iz+1);

}

}

}

}

m_fGWConnected = fMTConnected && fMOConnected && fMTAndMOConnected;

Release

停止网关服务。

停止网关服务时,将停止内建线程池运行,断开所有的网关连接。

virtual void Release();

参数

返回值

注意

网关应用停止时,必须调用Release函数停止线程池和断开同网关的连接。

https://www.doczj.com/doc/716234737.html, 16

如果使用者不显式调用Release函数的话,在CMPPClient函数销毁时,接口库会自动调用Release函数。

示例代码

client‐>Release();

m_fGWConnected = FALSE

Submit

发送一条Submit消息 。

int Submit(cmpp_submit & message);

参数

Message

[输入参数]cmpp_submit消息结构体。调用Submit函数之前需要首先对message

结构中的相关字段进行赋值。

返回值

如果函数调用成功,返回值0;否则返回相应的错误码。

注意

接口库的消息发送采用异步方式,这里的Submit操作仅仅是把消息提交给了中间件去发送,具体有没有发送成功,有没有收到回复(SUBMIT_RESPONSE)需要在消息触发函数中进行处理。

示例代码

CMPP_SUBMIT msg;

ZeroMemory(&msg, sizeof(CMPP_SUBMIT));

msg.nMsgid = 0;

/**

下面注释掉的字段用于业务处理

recid用于唯一标识一条消息,submittimes记录该消息的重发次数,用于重发

可以根据自己的情况赋值

https://www.doczj.com/doc/716234737.html, 17

由于submit消息的发送是异步的,所以需要根据recid和SubmitResponse中的seqid对应一条消息

*/

//msg.nonStdMessage.recid =;

//msg.nonStdMessage.submittimes = 0;

strncpy(msg.sAtTime, (const char *)(LPCTSTR)m_sAtTime, 17);

msg.uchDstUsrTl = m_bDestUserCount;

strncpy(msg.sDstTerminalId, (const char *)(LPCTSTR)m_sDestTerminalId,

/*32*/21*m_bDestUserCount);

strncpy(msg.sFeeCode, (const char *)(LPCTSTR)m_sFeeCode, 6);

strncpy(msg.sFeeTerminalId, (const char *)(LPCTSTR)m_sFeeTerminalId, /*32*/21);

strncpy(msg.sFeeType, (const char *)(LPCTSTR)m_sFeeType, 2);

//strncpy(msg.sLinkId, (const char *)(LPCTSTR)m_sLinkId, 20);

strncpy(msg.sMsgContent, (const char *)(LPCTSTR)m_sMsgContent, m_bMsgLen > 160 ?

160 : m_bMsgLen);

strncpy(msg.sMsgSrc, (const char *)(LPCTSTR)m_sMsgSrc, 6);

strncpy(msg.sServiceId, (const char *)(LPCTSTR)m_sServiceId, 10);

strncpy(msg.sSrcId, (const char *)(LPCTSTR)m_sSrcId, 21);

strncpy(msg.sValidTime, (const char *)(LPCTSTR)m_sValidTime, 17);

//msg.uchDestTerminalType = m_bDestTerminalType;

msg.uchDstUsrTl = m_bDestUserCount;

//msg.uchFeeTerminalType = m_bFeeTerminalType;

msg.uchFeeUserType = m_bFeeUserType;

https://www.doczj.com/doc/716234737.html, 18

msg.uchMsgFmt = m_bMsgFmt;

msg.uchMsgLength = m_bMsgLen;

msg.uchMsgLevel = m_bMsgLevel;

msg.uchPkNumber = m_bPkNumber;

msg.uchPkTotal = m_bPkTotal;

msg.uchRegisteredDelivery = m_bNeedReport;

msg.uchTpPid = m_bTpPid;

msg.uchTpUdhi = m_bTpUdhi;

// 开始发送

client‐>Submit(msg);

https://www.doczj.com/doc/716234737.html, 19

3.CMPPClient的消息和事件处理函数

OnConnectionLogined

登录网关成功时调用

virtual void OnConnectionLogined(CMPPConnection & connection)

参数

Connection

[输入参数]参数是成功登录而返回的CMPPConnection对象。

返回值

注意

示例代码

OnConnectionLoginFailed

登录网关失败时调用。

virtual void OnConnectionLoginFailed(

CMPPConnection & connection,

int errorCode

)

参数

connection

[输入参数]登录网关失败的CMPPConnection对象。

errorCode

[输入参数]登录网关失败的错误码。

返回值

https://www.doczj.com/doc/716234737.html, 20

相关主题
文本预览
相关文档 最新文档