1.1 开发第一个客户端程序
本节学习如何开发DLLTestClient客户端应用程序,访问远程RCA应用组件。
1.1.1 DLLTestClient.cpp文件
新建一个DLLTestClient.cpp文件,或者利用VC新建一个普通控制台应用程序工程项目:
1.1.2 添加头文件
#include <CGCLib/CGCLib.h>
using namespace cgc;
1.1.3 链接库文件
利用CGCLib开发客户端应用程序,需要CGCClass和CGCLib库的支持,如果是win32编译环境,在<CGCLib/CGCLib.h>文件里面,已经默认添加库的编译链接;
#ifdef WIN32
#ifdef _DEBUG
#pragma comment(lib,"CGCLibd.lib")
#else
#pragma comment(lib, "CGCLib.lib")
#endif // _DEBUG
#endif // WIN32
如果是Linux环境,请链接libCGCClass.a和libCGCLib.a库文件。
1.1.4 定义一个事件处理器
CGCLib采用异步通信机制,需要定义事件处理器,用于接收所有MYCP事件,包括SESSION会话事件、调用函数(如HelloUser)事件,等等,全部源码如下:
class MyCgcClientHandler
:public CgcClientHandler
{
private:
virtual voidOnCgcResponse(const cgcParserSotp &response)
{
// Open DLLTest module session return.
if (response.isResulted() &&response.isOpenType())
{
std::cout<< "SESSION: ";
std::cout<< response.getSid().c_str() << std::endl;
}
// Call HelloUser() function return.
if (response.getSign() == const_CallId_HelloUser)
{
cgcParameter::pointerpHi = response.getRecvParameter(_T("Hi"));
if (pHi.get() != NULL)
std::cout<< _T("[RETURN]:") <<pHi->getStr().c_str() << std::endl;
// response.getResultString() == response.getResultValue()
std::cout<< _T("[ResultCode]:")<< response.getResultValue() << std::endl;
return;
}
}
virtual voidOnCgcResponse(const unsignedchar * recvData, size_t dataSize)
{
std::cout<< _T("[OnCgcResponse]:")<< recvData << std::endl;
}
virtual voidOnCidTimeout(unsigned longcallid, unsigned longsign, bool canResendAgain){}
};
1.1.5 初始化
使用CSotpClient类初始化通信环境;
CSotpClient是一个SOTP协议客户端封装类,使用CSotpClient访问远程MYCP RCA组件;连接MYCP服务,设置事件处理器等,源码如下:
CSotpClient gCgcClient;
DoSotpClientHandler::pointergSotpClientHandler;
MyCgcClientHandler gMyCgcClientHandler;
void cgc_start(void)
{
std::cout<< _T("ADDR(ip:port):");
CCgcAddress::SocketTypest(CCgcAddress::ST_UDP);
tstringsIp;
std::getline(std::cin,sIp);
if (sIp.empty())
{
sIp= _T("127.0.0.1:8012");
}
cgc_stop();
gSotpClientHandler= gCgcClient.startClient(CCgcAddress(sIp, st));
BOOST_ASSERT(gSotpClientHandler.get()!= NULL);
// Specifies an event handler.
gSotpClientHandler->doSetResponseHandler(&gMyCgcClientHandler);
std::cout<< _T("APP Name:");
tstringappname;
std::getline(std::cin,appname);
if (appname.empty())
appname= _T("DLLTest");
std::cout<< _T("StartClient ")<< sIp.c_str() << "..."<< std::endl;
// Specify the connection module name.
gSotpClientHandler->doSetAppName(appname);
}
主要源码介绍:
CCgcAddress::SocketType st(CCgcAddress::ST_UDP);
设置UDP连接地址类型;
CSotpClient gCgcClient;
DoSotpClientHandler::pointergSotpClientHandler;
gSotpClientHandler =gCgcClient.startClient(CCgcAddress(sIp, st));
连接MYCP系统,并返回DoSotpClientHandler对象,所有跟MYCP的交互都通过返回的DoSotpClientHandler对象进行操作。
gSotpClientHandler->doSetAppName(appname);
连设置要连接的MYCP组件名称。
1.1.6 调用HelloUser函数
调用HelloUser函数,源码如下:
void cgc_call_hellouser(void)
{
BOOST_ASSERT(gSotpClientHandler.get()!= NULL);
std::cout<< "UserName:";
tstringuserName;
std::getline(std::cin,userName);
if (userName.empty())
userName= _T("Akeeyang");
// Set UserName parameter.
gSotpClientHandler->doAddParameter(CGC_PARAMETER("UserName", userName));
// Call HelloUser() function.
gSotpClientHandler->doSendAppCall(const_CallId_HelloUser,_T("HelloUser"));
}
主要源码介绍:
gSotpClientHandler->doAddParameter(CGC_PARAMETER("UserName",userName));
调用输入参数“UserName”的值;
gSotpClientHandler->doSendAppCall(const_CallId_HelloUser,_T("HelloUser"));
执行调用HelloUser函数;const_CallId_HelloUser为事件标识,后台返回时带回该事件标识,用于标识调用某个函数返回,详细看处理返回事件源码。
1.1.7 处理返回事件
返回事件处理源码如下:
virtualvoid OnCgcResponse(constcgcParserSotp & response)
{
//Open DLLTest module session return.
if(response.isResulted() && response.isOpenType())
{
std::cout << "SESSION: ";
std::cout <<response.getSid().c_str() << std::endl;
}
//Call HelloUser() function return.
if(response.getSign() == const_CallId_HelloUser)
{
cgcParameter::pointerpHi = response.getRecvParameter(_T("Hi"));
if (pHi.get() != NULL)
std::cout <<_T("[RETURN]:") <<pHi->getStr().c_str() << std::endl;
// response.getResultString() == response.getResultValue()
std::cout << _T("[ResultCode]:") <<response.getResultValue() << std::endl;
return;
}
}
主要源码介绍:
if (response.isResulted() &&response.isOpenType())
第一次执行MYCP后台组件,会默认打开一个SESSION连接,返回SESSION事件。
if (response.getSign() ==const_CallId_HelloUser)
{
cgcParameter::pointerpHi = response.getRecvParameter(_T("Hi"));
if(pHi.get() != NULL)
std::cout<< _T("[RETURN]:") << pHi->getValue().c_str() <<std::endl;
}
判断是否是调用HelloUser函数(const_CallId_HelloUser事件标识)返回,如果是取出Hi参数,并打印到系统屏幕上。
1.1.8 关闭SESSION连接
成功打开某个组件SESSION后,可以访问该组件的所有开放函数,在最后退出的时候,关闭SESSION会话,源码如下:
void cgc_stop(void)
{
if (gSotpClientHandler.get() != NULL)
{
gCgcClient.stopClient(gSotpClientHandler);
gSotpClientHandler.reset();
}
}
1.1.9 总结
本节学习如何开发一个MYCP客户端应用程序,包括定义事件处理器,指定要连接的组件名称,调用组件函数,标识事件,处理返回事件等;
至此,你已经学会基本的MYCP开发流程,包括后台应用组件和客户端应用程序的开发,你可以利用目前学到的知识,开发大部分的通信服务;
通过后面的一些高级课程,你可以学习到更多高级的开发技艺,比如系统及组件管理、数据对象存储管理、配置管理、日志服务、多线程编程,等等。