📄 sgipapi.h
字号:
//*************************************************************************************************************// 文件名称: SGIP.h// 实现功能: 中国联通短消息业务联网协议1.2版(sgip1.2 最新0213升级版)头文件.// 文件作者: PrinceToad(范圣刚,北京风起水流软件工作室)// 软件声明: 免费提供SP短消息网关开发接口库下载使用(CMPP3.0,SGIP1.2,CMPP2.0)
// V1.61 May.07.06
// 1.修正了上行连接线程安全的一个Bug.
//
// V1.6 Mar.25.06
// 1.加入了是否对网关登录SP的用户名口令进行验证的配置和参数。
// 2.加入了对网关连接SP的最大连接数进行配置的参数。
// 3.增加了输出调试日志的接口。
// 4.增加了允许设定线城池的工作线程数的参数配置。
// 5.支持输出SMG到网关的连接的连接数,SOCKET句柄,和远程端口(可以在外部关闭网关连接)。
// 6.回调函数返回值改为int.(允许在回调函数中返回值)
// 7.修正了一些BUG.
//
// V1.42 Jul.30.04
// 1.不对SUBMIT消息的MSGCONTENT长度作限制,原来的长度限制160,现在只要整个消息包不超过2K就可以.
// V1.41 Jul.30.04
// 1.加入了对MO连接远程服务器IP地址的判断,防止非法攻击!
// 2.彻底修正了MT断开重连,再发消息的Bug,MTRESP不会再返回255的错误.
// V1.4 Jul.19.04
// 1.修正了一个返回函数指针错误的问题。.(Special Thanks mate.)
// 2.增加了了程序启动模式,在Start函数里,当指定nLocalPort = -1时,不建立本地监听,只执行发送模块;
// 当指定nPeerPort = -1时,只进行监听,接收MO消息,不建立同网关的连接.
// V1.36 Jun.07.04
// 1.修改了多连接分配时候的一个Bug,该Bug能够导致在流量比较大的时候丢失MT消息。
// 2.去除了除试用版过期的以外的其他消息提示对话框。
// 3.Start函数里面加了一个参数fOutputDebugInfo,用来指示是否输出调试信息,
// 如果输出的话,DLL会在当前目录下建立一个文本文件debug.log,输出DLL的相关信息,
// 用作调试,出现错误情况时可以查看该文件。
// V1.34 Apr.13.04
// 1.修改了接收超时导致丢失MO消息的问题。
// V1.33 Mar.30.04
// 1.根据联通的最新修改,LinkId字段不作为两个整数来处理,直接作为8字节的字符串处理。
// V1.32 Mar.23.04
// 1.修改了连接中断后,重连的一个Bug.
// V1.3 Mar.07.04
// 1.修改了MT消息的发送方式,发送方式由原来的短连接(即一条消息建立一次连接)改为
// 现在的长连接,提高了发送效率,减轻了网关负担。
// 2.Start()函数增加了一个参数,允许用户自定义同网关建立的连接数,默认是3
// (网关连接数最好不要超过数值N, N = CPU个数*2 + 2)。
// V1.28 Feb.26.04
// 1.还是根据《SGIPV1.2协议适应性修改0120(SP分册)》作了相应修改。
// 2.根据协议变更,修改了Submit, Deliver, deliverstr结构体的定义,增加或者修改了Reserved,linkid字段。
// 3.修改了MO,MT消息收发函数.
// V1.27 Feb.16.04// 1.根据《SGIPV1.2协议适应性修改0120(SP分册)》作了相应修改.// V1.26 Jan.27.04// 1.修正了MTError时,mt_err结构提没有带回DateTime的错误。 // V1.25 Dec.22.03
// 1.在Submit函数中返回了submit消息包序列号中的时间戳(与Reponse和Report中的时间戳是对应的),
// 通过时间戳与序列号的结合彻底解决了序列号唯一对应的问题(哪怕是系统重新启动).
//
// V1.24 Dec.04.03
// 1.更正了在接收消息包时未给ReportStr中的nSubmitSeqId字段赋值的错误。
// 2.更正了MTError返回时不能带回序列号的问题.
// 3.在ReportStr字段中加入新的字段unsigned int nSubmitDateTime,用于保存更加详细的Report内容.
//
// V1.23 Nov.25.03
// 1.MTErrorStr和MTRespStr两个消息结构中增加一个sgipg_submit字段,用于返回其对应的SUBMIT消
// 息包,即这两个消息是由哪个SUBMIT包返回的,原因是SubmitResp包中并未包含开发者可能用到的必要信
// 息(如手机号码等,虽然这些信息在Report消息里面包含的比较全面)。
//
// V1.21 Nov.08.03
// 1.增加了函数CSgip::AddUserNumber(),可以方便地进行短消息群发.
// 2.增加了函数CSgip::GetSubmitSeqId(),功能是获得下一条submit消息的序列号.
// 在调用Submit()函数前调用可以提前获得将要发送的submit消息的序列号,类推的话,
// 下一条submit消息的序列号将在上一条消息序列号的基础上加3.这样的话就可以提前给submit消息编号,
// 然后等待submit_resp消息的到来。
// 3.CSgip::Submit()函数的原型由CSgip::Submit(sgipg_submit ss)变为
// CSgip::Submit(sgipg_submit ss, unsigned int &nSeq),输出参数nSeq的作用是返回submit消息的序列号.
//
// V1.2 Sep.11.03
//
//
//**************************************************************************************************************
/*
kenlistian 添加cpp部分,没测试过,仅供学习参考
*/
#ifndef _SMAL_SGIP_API_H
#define _SMAL_SGIP_API_H
#include "smal.h"
#include "threadpool.h"
#include "const.h"
#include "sgip_message.h"
#include <list>
using namespace std;
#ifdef SGIP_IMPORT
#define SGIP_API __declspec(dllimport)
#else
#define SGIP_API __declspec(dllexport)
#endif
#pragma warning(disable : 4251)
#pragma warning(disable : 4018)
class CSgip;
/*****************************************
SGIP JOB类
remoteport记录远程网关连接过来的端口号
下行线程(submit)
发送时应该创建工作,发送完就结束工作。
其中submit后处理response.处理完后结束工作
上行线程(deliver)
处于不断接受状态,有包来时处理,并response,
该线程处于论询recv状态,当有deliver时,打包递出事件,同时需repose,
当网关unbind,响应unbind_resp后关闭连接.
在accept后,开始上行工作,当网关unbind后处理完结束工作.
*/
class CJobSgip : public IJobDesc
{
public:
CJobSgip(SOCKET &hSocket, CSgip* sgip, unsigned remoteport); //网关连接sp
CJobSgip(sgipg_submit pss, CSgip* sgip, unsigned int nSeq, unsigned int nDateTime); //sp发送信息到网关
~CJobSgip();
void RecvMOProc(); //接受上行消息
void SendMTProc(); //下行发送消息
int nType; //类型. 估计 ntype = 1 是 上行,= 2是下行
private:
sgip_conn sp_conn; //网关连接sp信息结构体
CSgip* m_sgip;
sgipg_submit ss; //发送结构体
unsigned m_nSeq;
unsigned m_nDateTime;
};
//SGIP WORK类
class CWorkerSgip : public IWorker
{
public:
virtual void ProcessJob( IJobDesc* pJobDesc );
};
/*
网关连接sp信息
*/
class ConnInfo {
public:
ConnInfo() {
socketHandle = 0;
port = 0;
connectedTime = _T("");
}
ConnInfo(unsigned _socketHandle, unsigned _port, CString _connectedTime)
{
socketHandle = _socketHandle;
port = _port;
connectedTime = _connectedTime;
}
unsigned socketHandle; // 网关到SP的SOCKET句柄
unsigned port; // 网关的远程端口
CString connectedTime; // 网关到SP的连接连接时间
};
typedef std::list<ConnInfo> cList;
/*
SGIP协议封装类
*/
class SGIP_API CSgip{
friend class CJobSgip;
public:
CSgip(); // 初始化WinSock,初始化变量值
virtual ~CSgip(); // 释放WinSock
int Start(
char *sLocalIP,
int nLocalPort,
char *sPeerIP,
int nPeerPort,
char *sLoginName,
char *sLoginPwd,
int nConnType,
char *sSrcNum,
int nConnCount = 3,
char *sPeerName = NULL,
char *sPeerPwd = NULL,
unsigned nMaxSmgConn = 16,
unsigned nMinWorkThreadsCount = 4,
unsigned nMaxWorkThreadsCount = 8
);
void Release(BOOL forceRelease = FALSE);
int AddUserNumber(sgipg_submit* ss, const char* sUserNumber); //暂未处理。支持群发的设置目的号码的函数
// 提交MT消息,nSeq, nDateTime输出参数
void Submit(sgipg_submit ss,unsigned &nSeq,unsigned &nDateTime);
// 收到DELIVER上行消息时调用该函数
virtual int OnDeliver(DeliverStr & deliver) { return 0; }
// 收到状态报告时调用该函数
virtual int OnReport(ReportStr & report) { return 0; }
// 收到Submit应答消息时调用此函数
virtual int OnResponse(MTRespStr & response) { return 0; }
/*
发送SUBMIT消息失败时调用该函数
1:因为连接不上SMG网关系统
2:登录网关失败
3:包发送失败且超过重发次数
4. 超时无应答
5. 消息长度为零
6. 没有可用的连接
*/
virtual int OnMTError(MTErrorStr mterror) { return 0; }
// 获取当前网关到SP的连接列表
void GetSmgConnInfo(cList & _connList) {
_connList = connList;
return;
}
//得到网关到SP的连接数
unsigned GetSmgConnCount() { return (unsigned)connList.size(); }
/*
记录日志函数
*/
virtual int OnLogWrite(const char* pchFmt, ...) {
char buffer[1024] = "";
va_list arglist;
va_start( arglist, pchFmt );
_vsnprintf( buffer, 1024, pchFmt, arglist );
va_end(arglist);
TRACE(buffer);
return 0;
}
//提交的SUBMIT消息数
long GetSubmitCount() const { return submitCountTotal; }
//发送成功的SUBMIT消息数
long GetSubmitSucceedCount() const { return submitSucceedCountTotal; }
//得到发送失败的SUBMIT消息数
long GetSubmitFailedCount() const { return submitFailedCountTotal; }
//得到失败的SUBMITResponse消息数
long GetRespFailedCount() const { return respFailedCountTotal; }
//得到成功的SUBMITResponse消息数
long GetRespSucceedCount() const { return respSucceedCountTotal; }
//得到收到的Deliver消息数
long GetDeliverCount() const { return deliverCountTotal; }
//得到收到的StatusReport消息数
long GetStatusReportCount() const { return sreportCountTotal; }
protected:
unsigned int GetSubmitSeqId(); //得到下一条要发submit消息的序列号
//递增提交的SUBMIT消息数
long AddSubmitCount() { return ::InterlockedIncrement((long*)&submitCountTotal); }
//递增发送成功的SUBMIT消息数
long AddSubmitSucceedCount() { return ::InterlockedIncrement((long*)&submitSucceedCountTotal); }
//递增发送失败的SUBMIT消息数
long AddSubmitFailedCount() { return ::InterlockedIncrement((long*)&submitFailedCountTotal); }
//递增失败的SUBMITResponse消息数
long AddRespFailedCount() { return ::InterlockedIncrement((long*)&respFailedCountTotal); }
//递增成功的SUBMITResponse消息数
long AddRespSucceedCount() { return ::InterlockedIncrement((long*)&respSucceedCountTotal); }
//递增收到的Deliver消息数
long AddDeliverCount() { return ::InterlockedIncrement((long*)&deliverCountTotal); }
//递增收到的StatusReport消息数
long AddStatusReportCount() { return ::InterlockedIncrement((long*)&sreportCountTotal); }
protected:
int SubmitFunc(sgipg_submit ss, unsigned int nSeq, unsigned int nDateTime);
private:
bool LocalListen(); //本地监听
bool IsValidIPAddr(LPCTSTR sIPAddr); //是否有效的ip地址
sgip_conn* GetSubmitConn(int &nConnIndex); //获得submit的连接
void ChangeStatus(int nConnIndex, bool fBusy); //改变线程池状态
bool CreateLogFile(); //创建log文件
int LoginSmg(sgip_conn *pConn); //sp登陆网关
void LogoutSmg(sgip_conn *pConn); //sp退出网关
bool CreateConn(); //sp连接网关
bool ReleaseConn();
void AddSmgConn(unsigned socketHandle, unsigned port); //网关连接sp
void RemoveSmgConn(unsigned socketHandle);
CString GetDateTime();
unsigned GetMaxSmgConnections() { return m_nMaxSmgConn; } //网关连接sp的最大数目
private:
static DWORD WINAPI SgipServFunc(LPVOID pParam); //线程处理部分
virtual DWORD SgipServProc();
//int (*m_PDeliver)(DeliverStr deliver);
//int (*m_PReport)(ReportStr report);
//int (*m_PResponse)(MTRespStr response);
//int (*m_PMTError)(MTErrorStr mterror);
//int (*OnLogWrite)(const char* pchFmt, ...);
CString GetPeerName() { return m_sPeerName; }
CString GetPeerPwd() { return m_sPeerPwd; }
private:
BOOL m_fStarted; // 是否已经启动
BOOL m_fStop; // 系统停止标志
CThreadPool pool; // 线程池
CWorkerSgip m_worker;
CJobSgip *m_pJob;
CString m_sPeerAddr; // 网关IP地址
int m_nPeerPort; // 网关端口
CString m_sUserName; // 登录用户名
CString m_sPwd; // 登录口令
int m_nConnType; // 连接类型
int m_nSubmitConn; // SP到网关连接数
CString m_sSrcNum; // 原节点号码
CString m_sLocalIPAddr; // 本机地址
int m_nLocalPort; // 本地监听端口
CString m_sPeerName; // 网关登录SP的用户名
CString m_sPeerPwd; // 网关登录SP的口令
unsigned m_nMaxSmgConn; // 允许的网关到SP的最大连接数
CString m_sLogPath; // 日志文件路径
//BOOL m_fLogEvent; // 是否记录系统日志
unsigned m_nMinWorkThreadsCount; // 线程池初始线程数
unsigned m_nMaxWorkThreadsCount; // 允许的线程池最大线程数
SOCKET serverSocket; // 本地监听套接字
HANDLE m_hThread; // 本地监听线程的句柄
unsigned m_nCounter; // 消息的数量
int m_nConnIndex; // 连接索引
sgip_conn SubmitConn[MAX_PATH]; // SP到网关连接数组
CCriticalSection m_arrayCs; // 队列临界区
CCriticalSection m_listCs;
cList connList; // 网关连接队列
long submitCountTotal;
long submitSucceedCountTotal;
long submitFailedCountTotal;
long respSucceedCountTotal;
long respFailedCountTotal;
long deliverCountTotal;
long sreportCountTotal;
};
#endif // SGIP_API_H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -