前营中间件(5) - 异步发包和客户端的操作函数
来源:互联网 发布:淘宝小号一个月刷70单 编辑:程序博客网 时间:2024/05/07 12:56
上次,我们介绍了同步发送接收模式,现在我们介绍一下异步模式,下面是异步发送函数:
/**
* 函数名称:异步发送消息
* 函数功能:将数据发送出去,系统会自动打个发送标志,并把对应的序号写入消息中并返回,应答
* 序号写为。
* 参数列表:
* @uiSessionID : 会话ID
* @uiFuncNo : 功能号
* @usSendBuffHandle : 发送的数据包
* @usSeqNo : 数据包的序号
* @return : Z_OK——成功,< 0 ——失败
* 修改记录:20090908 赵海杰
*/
virtual int SendPack(unsigned int uiSessionID, unsigned int uiFuncNo, unsigned short usSendBuffHandle, unsigned short &usSeqNo) = 0;
它和同步发送相比,少了两个参数接收缓冲区和等待时间,多出另一个参数usSeqNo, usSeqNo为消息序号,由系统维护,可以用此值来匹配异步请求的应答包(不过一般情况下不会用到),别的参数没有什么特别,就不介绍了.
我们进行发送后,还需要接收,我们通过回调函数进行接收操作,下面是回调函数的定义:
/**
* 函数名称:接收应答回调函数
* 函数功能:用来处理就应答和主推两种方法发送过来的消息
* 参数列表:
* @lpParam : 客户传入的参数
* @uiSessionID : 接收到请求的会话号
* @usRecvBuffHandle: 接收数据缓冲区
* @usSequenceNo : 会话消息序号
* @lpPointer : 附加信息
* @Result : 处理结果,如果返回Z_OK说明被处理过了,不需要调用下一个回调函数进行处理,如果返回
* 非Z_OK,系统会调用下一个回调函数进行处理,如果会话层的回调函数链被调用完了,则调用全局的回调函数链处理。
* 修改记录:
* 20090329 赵海杰 创建
**/
typedef int (__stdcall *LPONRECVFUNC)(void* lpParam, unsigned int uiSessionID, unsigned short usRecvBuffHandle, unsigned short usSequenceNo, void* lpPointer);
第一个参数,为我们在添加回调函数时设置的值,第二个参数为会话号,第三个是接收数据所在的缓存区,第四个为消息序号,和发送时的序号是一样的,第四个值是一个标志位,此值指向一个字符,这个字符表示数据处理时发生的状态.这个值的定义在ZCommError.h中,如下:
enum ErrorNoList
{
// 通讯解包错误号,为CHAR型会记录在返回包中
EP_NORMAL = 0, // 正确消息包
EP_SYSTEM_ERROR, // 系统处理错误
EP_UNPACK_FAILED, // 解包错误
EP_CLOSE_SESSION, // 关闭会话的消息
EP_CREATE_SESSION, // 创建会话的消息
EP_EXCEED_ROUTER, // 路由超限,中间经过的中间件太多
EP_NO_ROUTER, // 没有合知的路由
…..
}
我们在处理回调函数中,要对这个值进行判断,回调函数返回Z_OK,表示处理成功.
我们定义好回调函数后,就需要把回调函数设置到系统中,我们提供两个函数,一个函数,把回调函数添加到全局中,可以处理所有的异步消息;一个函数,把回调函数添加到会话中,只能处理会话的异步消息.当然,我们的异步消息会先调用会话的回调函数,如果会话的回调函数,没有处理此异步消息的功能(即返回非Z_OK值),才会调用全局的回调函数,下面两个声明,第一个是添加全局的回调函数,第二个是添加会话的回调函数,两个函数最后一个参数,是客户传入的参数,会原样不动的传给回调函数的第一个参数.
/**
* 函数名称:添加一个全局的应答处理回调函数
* 函数功能:将此回调函数添加到应答处理回调函数链的头部
* 参数列表:
* @lpOnRecvFunc : 回调函数指针
* @lpParam : 传入的参数
* @return : Z_OK——成功,< 0 ——失败
* 修改记录:20090908 赵海杰
*/
virtual int AddOnRecvFunc(LPONRECVFUNC lpOnRecvFunc, void* lpParam) = 0;
/**
* 函数名称:添加一个会话的应答处理回调函数
* 函数功能:将此回调函数添加到应答处理回调函数链的头部
* 参数列表:
* @uiSessionID : 会话ID
* @lpOnRecvFunc : 回调函数指针
* @lpParam : 传入的参数
* @return : Z_OK——成功,< 0 ——失败
* 修改记录:20090908 赵海杰
*/
virtual int AddOnRecvFunc(unsigned int uiSessionID, LPONRECVFUNC lpOnRecvFunc, void* lpParam) = 0;
无论对会话还是全局都可以添加多个回调函数,在调用时,会先调用后添加的,当回调函数返回非Z_OK,才会调用先前添加的. RemoveOnRecvFunc是删除回调函数的功能,它也提供两个函数,分别删除全局或会话私有的回调函数.
下面是异步回调函数的例子,从ClientTest中可以取到相应的代码.
int __stdcall OnRecv(void* lpParam, unsigned int uiSessionID, unsigned short usRecvBuffHandle, unsigned short usSequenceNo, void* lpPointer)
{
char cFlag = *(char*)lpPointer;
char szBuff[1024];
unsigned char ucRouterFlag(0);
unsigned int uiFuncNo;
unsigned long iBuffLen(1024);
CTime t(time(NULL));
CString str;
if(EP_CREATE_SESSION == cFlag)
{
str.Format("功能号:000] 新会话建立,会话号:%d/r/n", uiSessionID);
str = t.Format("[%H-%M-%S-接收-") + str;
}
else if(EP_CLOSE_SESSION == cFlag)
{
str.Format("功能号:000] 会话关闭,会话号:%d/r/n", uiSessionID);
str = t.Format("[%H-%M-%S-接收-") + str;
}
else if(EP_NO_ROUTER == cFlag)
{
lpClientAPI->GetFuncNo(usRecvBuffHandle, uiFuncNo);
str.Format("功能号:%d] 没有路由可以转发,会话号:%d/r/n", uiFuncNo, uiSessionID);
str = t.Format("[%H-%M-%S-接收-") + str;
}
else if (EP_NORMAL == cFlag)
{
int iRet(0);
lpClientAPI->GetRouterFlag(usRecvBuffHandle, ucRouterFlag);
if (0 == ucRouterFlag)
{
int iRet = lpClientAPI->DetachBuffer(usRecvBuffHandle, szBuff, iBuffLen);
szBuff[iBuffLen] = 0;
lpClientAPI->GetFuncNo(usRecvBuffHandle, uiFuncNo);
if(0 == iRet)
{
str.Format("功能号:%d] %s/r/n", uiFuncNo, szBuff);
str = t.Format("[%H-%M-%S-接收-") + str;
}
}
else if(BROADCAST_ROUTER_INFO == ucRouterFlag)
{
iRet = lpClientAPI->DetachBuffer(usRecvBuffHandle, szBuff, iBuffLen);
if(0 == iRet)
{
szBuff[iBuffLen] = 0;
lpClientAPI->GetFuncNo(usRecvBuffHandle, uiFuncNo);
str.Format("功能号:%d] %s/r/n", uiFuncNo, szBuff);
str = t.Format("[%H-%M-%S-广播-") + str;
}
}
else if(MULTICAST_ROUTER_INFO == ucRouterFlag)
{
iRet = lpClientAPI->DetachBuffer(usRecvBuffHandle, szBuff, iBuffLen);
if(0 == iRet)
{
szBuff[iBuffLen] = 0;
lpClientAPI->GetFuncNo(usRecvBuffHandle, uiFuncNo);
str.Format("功能号:%d] %s/r/n", uiFuncNo, szBuff);
str = t.Format("[%H-%M-%S-多播-") + str;
}
}
else if(MULTICAST_ROUTER_REMOVE == ucRouterFlag)
{
lpClientAPI->GetFuncNo(usRecvBuffHandle, uiFuncNo);
str.Format("功能号:%d] 删除多播/r/n", uiFuncNo);
str = t.Format("[%H-%M-%S-多播-") + str;
}
else if(MULTICAST_ROUTER_ADD ==ucRouterFlag)
{
lpClientAPI->GetFuncNo(usRecvBuffHandle, uiFuncNo);
str.Format("功能号:%d] 添加多播/r/n", uiFuncNo);
str = t.Format("[%H-%M-%S-多播-") + str;
}
else if(BROADCAST_ROUTER_RESET ==ucRouterFlag)
{
lpClientAPI->GetFuncNo(usRecvBuffHandle, uiFuncNo);
str.Format("功能号:%d] 广播重置/r/n", uiFuncNo);
str = t.Format("[%H-%M-%S-广播-") + str;
}
else
{
int iRet = lpClientAPI->DetachBuffer(usRecvBuffHandle, szBuff, iBuffLen);
if(0 == iRet)
{
szBuff[iBuffLen] = 0;
lpClientAPI->GetFuncNo(usRecvBuffHandle, uiFuncNo);
str.Format("功能号:%d] %s/r/n", uiFuncNo, szBuff);
str = t.Format("[%H-%M-%S-未知-") + str;
}
}
}
else
{
str.Format(" 错误,错误标识:%d/r/n", cFlag);
str = t.Format("[%H-%M-%S-接收]") + str;
}
return 0;
}
在上面的代码中,有两个函数是我们没用的, GetFuncNo是取功能号的,功能号保存在缓存区中, GetRouterFlag是取消息包路由方式,可以由这个值得到,此消息是普通消息包,还是多播包或广播包.对于多播和广播的相关信息,我们以后再谈,此先了解.
现在我们把的LPCLIENTAPI函数基本上都认识了,还剩下以下几个:
GetVersion取得接口的版本号,客户使用时,先调用此函数取得版本号和接口文件上的版本号API_VERSION相比较,如果版本不匹配,需要进行出错处理,这个函数是为了防止DLL HELL的问题.
CloseMultiCast关闭多播,我们订阅多播后,可以在客户端进行关闭,因为多播也是以功能号为基础的,所以此函数需要提供会话号和功能号.关于多播的相关知道,我们其后再讲.
GetDataSize获得缓存区数据的大小.
GetConnectStatus获取连接状态.
最后三个函数都是与数据包打包器相关的,我们以后再介绍.
好了,现在客户端所提供的所有功能,我们都了解了.我们下次将会讲一下组件开发包的接口.
- 前营中间件(5) - 异步发包和客户端的操作函数
- 前营中间件(4) - 客户端的实现
- Redux(二: 中间件和异步操作)
- 简单的ssl发包客户端
- C#客户端的异步操作
- C#客户端的异步操作
- C#客户端的异步操作
- C#客户端的异步操作
- 前营中间件(3) - 组件的开发
- 前营中间件(6) - 组件的接口
- 常用的curl发包函数
- Redux:中间件与异步操作
- 异步操作和async函数
- 发包函数
- iOS发包前注意事项
- 前营中间件(2) - 配置
- 再谈用strace函数来查看网络发包的目的地ip和port
- ECMAScript6标准异步操作和Async函数
- mysql插入速度调优心得
- CSS hack之区别不同浏览器兼容的写法
- Android 的AT命令协议栈初始化
- UltraEdit中将指定内容替换成回车换行
- Solaris10中级读书笔记之二:管理本地磁盘设备
- 前营中间件(5) - 异步发包和客户端的操作函数
- 文件操作系列之二——(标准C++文件流)
- 阿尔法 计算机分析
- Object-C 简介
- DRP
- Magento搜索引擎优化(SEO)
- 最后的结果,迫于种种压力调解了,一倍都没有拿到
- oracle中检查2个数字型字段合并显示后内容是否有非数字的问题
- 【模拟】【RQNOJ】汇编语言