基于TCP协议的短信数据包打包与解包及应用
孟培远 05-09-16 11:30
首先是CMPPClient.cpp中执行主函数main(),调用bool CMPPClientStart(),首先绑定套接字cmpp.bind(),然后连接数据库,循环判断是否有信息要发送,如果有信息发送,则提交要发送的信息iRet = cmpp.SubmitSM(),判断提交的结果,分别进行处理,更新数据库中短信发送状态, 接收从短信中心来的数据iStatus = cmpp.RecvDataFromSMC(lCommandId, osRecvData),根据接收的状态进行判断处理,如果状态为MSG_SUCCESS,则进行判断各种命令,并进行处理,如果命令为CMPP_DELIVER,则进行iRet = cmpp.DeliverSM(),判断结果,并根据结果进行相应的处理
这个部分主要是短信的接收与发送,分别在两个不同进程中实现3888中为:cmcc.cpp和recv.cpp,其实发送与接收的程序基本相同,主要是接收recv.cpp中把发送的代码屏蔽了.
在02166中是CMPPClient.cpp发送与接收代码同在一个进程中进行运行.
下面主要就02166的代码进行说明:
CMPP.cpp的主要功能是,对数据打包解包以及各种数据的更改进行封装到具体函数内,CMPP.cpp主要是调用CMPPduCode.cpp和Socket.cpp里面的函数进行数据的打包,解包,发送与接收.
CMPP.cpp的主要函数及功能说明如下:
制作连接数据包
MakeConnectPDU(char* p_pSystemID, char* p_pPasswd, Octstr& p_OctStr)
(调用m_PduCode.Pdu_Encode_Connect(PDUConnect, p_OctStr);进行连接数据打包)
制作发送信息数据包
MakeSmsSendPDU( char p_cPkTotal,char p_cPkNumber,char p_cRegisteredDelivery,
char p_cMsgLevel,char* p_pServiceId,char p_cFeeUserType,char* p_pFeeTerminalId,
char p_cFeeTerminalType,char p_cTPpid,char p_cTPudhi, char p_cMsgFmt,
char* p_pMsg_src, char* p_pFeeType, char* p_pFeeCode, char* p_pValidTime,
char* p_pAtTime, char* p_pSrcId,char* p_pDestTerminalId,char p_cDestTerminalType,
char p_cMsgLength,char* p_pMsgContent,char* p_pLinkID,Octstr& p_OctStr)
(调用m_PduCode.Pdu_Encode_Submit(PduSubmitSm, p_OctStr); 提交信息打包)
制作接收回应数据包
MakeDeliverRespPDU(long p_lSeqNum,char* p_pMsgId,long p_cResult, Octstr& p_OctStr)
(调用m_PduCode.Pdu_Encode_Deliver_Resp(p_lSeqNum, PDUDeliverResp, p_OctStr);信息打包)
制作测试数据包
MakeActiveTestPDU(Octstr& p_OctStr)
(调用m_PduCode.Pdu_Encode_ActiveTest(p_OctStr);进行数据打包)
制作测试回应数据包
MakeActiveTestRespPDU(long p_lSeqNum, Octstr& p_OctStr)
(调用m_PduCode.Pdu_Encode_ActiveTest_Resp(p_lSeqNum, p_OctStr);进行数据打包)
制作终止数据包
MakeTerminatePDU(Octstr& p_OctStr)
(调用m_PduCode.Pdu_Encode_Terminate(p_OctStr);)
制作终止回应数据包
MakeTerminateRespPDU(long p_lSeqNum, Octstr& p_OctStr)
(调用m_PduCode.Pdu_Encode_Terminate_Resp(p_lSeqNum, p_OctStr);进行数据打包)
绑定
Bind(string& p_strHost, int p_iPort, string& p_strSystemID, string& p_strPasswd)
(调用ReBind())
根据已保存的参数,重新绑定到短讯中心
ReBind()
(调用MakeConnectPDU((char*)m_strSystemID.c_str(), (char*)m_strPasswd.c_str(), osSendData);进行数据打包,然后发送信息进行测试是否连接)
释放与短讯中心的绑定
UnBind()
(调用m_socket.Close();进行断开套接字)
发送短消息
(1) SubmitSM(long& p_lSeqNum, cmpp_pdu_submit_sm& p_PduSubmit)
(调用(3) SubmitSM() )
发送短消息
(2) SubmitSM(long& p_lSeqNum,int p_iPkTotal,int p_iPkNumber,int p_iRegisteredDelivery,
int p_iMsgLevel,string p_strServiceId,int p_iFeeUserType,string p_strFeeTerminalId,
int p_iFeeTerminalType, //(3.0中添加字段) int p_iTPpid,int p_iTPudhi,int p_iMsgFmt,
string p_strMsgSrc, string p_strFeeType,string p_strFeeCode,string p_strValidTime,
string p_strAtTime, string p_strSrcId,string p_strDestTerminalId, int p_iDestTerminalType, //(3.0中添加字段)int p_iMsgLength,string p_strMsgContentHex,string p_strLinkID)
(调用(1) SubmitSM())
发送短消息
(3) SubmitSM(long& p_lSeqNum,char p_cPkTotal,char p_cPkNumber,char p_cRegisteredDelivery,
char p_cMsgLevel,char* p_pServiceId,char p_cFeeUserType,char* p_pFeeTerminalId,
char p_cFeeTerminalType,char p_cTPpid,char p_cTPudhi, char p_cMsgFmt, char* p_pMsg_src,char* p_pFeeType,char* p_pFeeCode,char* p_pValidTime,char* p_pAtTime,
char* p_pSrcId,char* p_pDestTerminalId, char p_cDestTerminalType, //(3.0中添加字段)
char p_cMsgLength,char* p_pMsgContent,char* p_pLinkID) //(3.0中添加字段)
(调用MakeSmsSendPDU( p_cPkTotal, p_cPkNumber, p_cRegisteredDelivery, p_cMsgLevel,
p_pServiceId, p_cFeeUserType, p_pFeeTerminalId, p_cFeeTerminalType, p_cTPpid,
p_cTPudhi, p_cMsgFmt, p_pMsg_src, p_pFeeType, p_pFeeCode, p_pValidTime, p_pAtTime, p_pSrcId, p_pDestTerminalId, p_cDestTerminalType, p_cMsgLength, p_pMsgContent,
p_pLinkID, osSendData);对要发送的数据进行打包,然后m_socket.Send((char*)osSendData.data, osSendData.len);发送数据,再调用m_socket.Receive((char*)osRecvData.data, osRecvData.len);接收发送后的返回信息,调用 iResult = m_PduCode.Pdu_Decode_Submit_Resp(osRecvData, PduHead, PduSubmitResp);对接收到的数据进行解包,返回解包成功与否的信息)
提交短信回复信息(提交完信息后回复过来的信息,进行解包)
SubmitSMResp(string& p_strMsgIdHex,Octstr& p_OctStr)
(调用m_PduCode.Pdu_Decode_Submit_Resp(p_OctStr, PduHead, PduSubmitResp);进行数据解包)
接收短信中心下发数据
RecvDataFromSMC(long& p_lCommandId, Octstr& p_osRecvData)
(调用m_socket.Receive((char*)p_osRecvData.data, p_osRecvData.len);接收数据,调用m_PduCode.Pdu_Decode_Command(p_osRecvData);进行数据解包)
接收从短信中心发送过来或者从其他网关转发过来的短信传给SP
(1)DeliverSM( Octstr& p_OctStr,long& p_lSeqNum,string& p_pMsgIdHex,string& p_pDestId,
string& p_pServiceId,int& p_TPpid,int& p_TPudhi,int& p_MsgFmt, string& p_pSrcTerminalId,
int& p_SrcTerminalType, //(3.0中添加字段)int& p_RegisteredDelivery,int& p_MsgLength,
string& p_pMsgContentHex, string& p_pLinkID) //(3.0中添加字段)
(调用(2)DeliverSM(p_OctStr, p_lSeqNum, szMsgId, szDestId, szServiceId, cTPpid, cTPudhi,
cMsgFmt, szSrcTerminalId, cSrcTerminalType,cRegisteredDelivery, cMsgLength,szMsgContent, szLinkID);进行数据赋值)
对接收到数据是短信下发进行解包处理
(2) DeliverSM( Octstr& p_OctStr,long& p_lSeqNum,char* p_pMsgId, char* p_pDestId,
char* p_pServiceId,char& p_TPpid,char& p_TPudhi,char& p_MsgFmt,char* p_pSrcTerminalId,
char& p_SrcTerminalType, //(3.0中添加字段)char& p_RegisteredDelivery,
char& p_MsgLength,char* p_pMsgContent, char* p_pLinkID)//(3.0中添加字段)
(调用MakeDeliverRespPDU(PduHead.sequence_id, (char*)PduDeliver.Msg_Id, cResult, osSendData);进行数据接收, m_socket.Send((char*)osSendData.data, osSendData.len);发送信息到短信中心)
活动测试(活动测试要求(10~15秒)就需发送测试)
ActiveTest()//动态测试
(调用MakeActiveTestPDU(osSendData);进行数据打包m_socket.Send((char*)osSendData.data, osSendData.len);发送数据包, m_socket.Receive((char*)osRecvData.data, osRecvData.len);接收数据包, m_PduCode.Pdu_Decode_ActiveTest_Resp(osRecvData, PduHead);接收到的数据包进行解包)
对接收到数据是活动测试进行解包处理
ActiveTestResp(Octstr& p_OctStr)
(调用m_PduCode.Pdu_Decode_ActiveTest(p_OctStr, PduHead)进行数据解包MakeActiveTestRespPDU(PduHead.sequence_id, osSendData);对是数据进行打包m_socket.Send((char*)osSendData.data, osSendData.len); 发送数据到短讯中心)
请求拆除连接
Terminate()
(调用MakeTerminatePDU(osSendData);进行请求断开的数据进行打包, m_socket.Send((char*)osSendData.data, osSendData.len); 发送数据到短讯中心m_socket.Receive((char*)osRecvData.data, osRecvData.len);从短信中心接收数据包, m_PduCode.Pdu_Decode_Terminate_Resp(osRecvData, PduHead);对接收到的数据进行解包)
对接收到数据是请求拆除连接进行解包处理
TerminateResp(Octstr& p_OctStr)
(调用m_PduCode.Pdu_Decode_Terminate(p_OctStr, PduHead)进行数据解包, MakeTerminateRespPDU(PduHead.sequence_id, osSendData);对回应的数据进行打包m_socket.Send((char*)osSendData.data, osSendData.len);把回应的数据发送到短信中心)
在Socket.cpp中用到的主要是Send(),Receive()两个函数,分别用来发送数据和接受数据
具体函数如下:
连接函数
Connect(const string& p_strHost, int p_iPort)
发送函数
(1) Send(const char *p_pchBuf, int p_iLen, unsigned int p_iFlag)
发送函数
(2) Send(const string& p_strInfo, unsigned int p_iFlag)
发送(1)与发送(2)不同之处在于没有发送信息的长度
接收函数
(1) Receive(char *p_pchBuf, int p_iLen, unsigned int p_iFlag)
接收函数
(2) Receive(string& p_strInfo, unsigned int p_iFlag)
接收(1)与接收(2)不同之处在于没有接受信息的长度
而在CMPPduCode.cpp中则是打包和解包的详细操作:
包头解码(整型数据转主机字节序)//网络字节转化为主机字节
pdu_header_decode(cmpp_pdu_head& p_PduHead)
包头编码(整型数据转网络字节序)//主机字节转化为网络字节
pdu_header_encode(cmpp_pdu_head& p_PduHead)
解包获取命令
Pdu_Decode_Command(Octstr& p_OctData)
连接到短信中心数据打包 //连接到短信中心的数据进行打包
Pdu_Encode_Connect(const cmpp_pdu_connect& p_PduConnect, Octstr& p_OctStr)
连接到短信中心返回数据解包
Pdu_Decode_Connect_Resp(const Octstr& p_OctData, cmpp_pdu_head& p_PduHead, cmpp_pdu_connect_resp& p_PduConnectResp)
发送短信数据打包
Pdu_Encode_Submit(const cmpp_pdu_submit_sm& p_PduSubmit, Octstr& p_OctStr)
发送短信返回数据解包
Pdu_Decode_Submit_Resp(const Octstr& p_OctData, cmpp_pdu_head& p_PduHead, cmpp_pdu_submit_sm_resp& p_PduSubmitResp)
接收短信返回数据解包(CMPP_DELIVER是ISMG把从短信中心或其他ISMG转发来的短信交给SP
Pdu_Decode_Deliver(const Octstr& p_OctData, cmpp_pdu_head& p_PduHead, cmpp_pdu_deliver_sm& p_PduDeliver)
接收短信后要返回信息,进行数据打包
Pdu_Encode_Deliver_Resp(long p_lSeqNum, const cmpp_pdu_deliver_sm_resp& p_PduDeliverResp, Octstr& p_OctStr)
活动测试数据打包(SP --> ISMG 或 ISMG --> SP)
Pdu_Encode_ActiveTest(Octstr& p_OctStr)
活动测试数据解包
Pdu_Decode_ActiveTest(const Octstr& p_OctStr, cmpp_pdu_head& p_PduHead)
活动测试返回数据解包
Pdu_Decode_ActiveTest_Resp(const Octstr& p_OctStr, cmpp_pdu_head& p_PduHead)
活动测试返回数据打包
Pdu_Encode_ActiveTest_Resp(long lSeqNum, Octstr& p_OctStr)
请求拆除连接数据打包
Pdu_Encode_Terminate(Octstr& p_OctStr)//只有包头,没有包体
请求拆除连接数据解包
Pdu_Decode_Terminate(const Octstr& p_OctStr, cmpp_pdu_head& p_PduHead)
请求拆除连接返回数据解包
Pdu_Decode_Terminate_Resp(const Octstr& p_OctStr, cmpp_pdu_head& p_PduHead)
请求拆除连接返回数据打包
Pdu_Encode_Terminate_Resp(long lSeqNum, Octstr& p_OctStr)