编者:李国帅
qq:9611153 微信lgs9611153
时间:2012/03/12 08:37:09
背景原因:
走了一圈才发现,使用简单的技术可以解决的问题,没有必要玩那么多的技巧。
许多技巧听上去挺牛,挺能忽悠人,其实没啥用,还不好理解。
如果代码可以卖钱,可以显摆,或者有很好的理由,那倒可以用,否则还是怎么方便怎么做比较好。
1、最初,使用函数指针和消息映射的方法
typedef void (CMessageMng::* PFUNCPROC)(void*);//处理函数
class CMessageMng
{
...
map<UINT,PFUNCPROC> m_mapMsgHandle;//消息和处理的映射
void HandleRespLogin(void* pData);//处理登录消息
void HandleRespLogout(void* pData);//处理登录消息
void HandleRespHeartbeat(void* pData);//处理登录消息
void InitMsgHandle();//初始化处理函数
void HandleNetItem(NetDataItem& rItem);//消息分析入口
}
void CMessageMng::HandleNetItem(NetDataItem& rItem)
{
if (rItem.nMsgId != UMSG_CLIENTHEARTBEAT && rItem.nMsgId != UMSG_INFORMDEVSTATUS && rItem.nMsgId != UMSG_INFORMALARM)
{
CDataHandle::Instance()->PrintfLog(LOG_INFO,"%s, Get nMsgId=%d \n",__FUNCTION__,rItem.nMsgId);
}
PFUNCPROC pHandle = m_mapMsgHandle[rItem.nMsgId];
_ASSERT(pHandle);//对接收到的数据进行分类
if(pHandle)
{
void* pData = &rItem;
(this->*pHandle)(pData);
}
}
void CMessageMng::InitMsgHandle()
{
//消息和处理的映射
PFUNCPROC pHandle = &CMessageMng::HandleRespLogin;
m_mapMsgHandle[UMSG_LOGIN]=pHandle;//登陆
m_mapMsgHandle[UMSG_LOGOUT]=&CMessageMng::HandleRespLogout;//退出//不处理
m_mapMsgHandle[UMSG_GETRIGHTS]=NULL;//取得权限信息
m_mapMsgHandle[UMSG_GETINITDATA]=NULL;//获取初始化信息
m_mapMsgHandle[UMSG_CLIENTHEARTBEAT]=&CMessageMng::HandleRespHeartbeat;//客户端心跳
m_mapMsgHandle[UMSG_GETNODETREE]=NULL;//查询节点树
...
}
void CMessageMng::HandleRespLogin(void* pData)
{
NetDataItem* pItem = (NetDataItem*)pData;
st_resp_LOGIN oLogin;
if (pItem->nMsgStatus == -1)//发送超时
{
strcpy(oLogin.Description,"发送超时");
}
else if (pItem->nMsgStatus == -2)//接收超时
{
strcpy(oLogin.Description,"接收超时");
}
else if (pItem->nMsgStatus == 2)//接收成功//处理消息
{
char* pInData = pItem->pDataRecv;
int nret = m_pXml2Data->UnpackegeUserLoginResponse(pInData,oLogin);
ATLASSERT(nret==0);//组装接收数据包,发送到处理模块处理
if (oLogin.Code == 0 && oLogin.UserId >= 0)
{
CreateThreadMsgHandle();//启动心跳
m_pDataHandle->GetInitialInfo();
}
}
m_pDataHandle->m_pDataMng->m_resp_LOGIN = oLogin;
MessageBox(NULL,oLogin.Description,"提醒",MB_OK);
m_pDataHandle->HandleNetCmdRecv(UMSG_LOGIN);
}
void CMessageMng::HandleRespLogout(void* pData)
{
NetDataItem* pItem = (NetDataItem*)pData;
st_resp_LOGOUT oLogout;
if (pItem->nMsgStatus == -1)//发送超时
{
strcpy(oLogout.Description,"发送超时");
}
else if (pItem->nMsgStatus == -2)//接收超时
{
strcpy(oLogout.Description,"接收超时");
}
else if (pItem->nMsgStatus == 2)//接收成功//处理消息
{
char* pInData = pItem->pDataRecv;
int nret = m_pXml2Data->UnpackegeUserLogoutResponse(pInData,oLogout);
ATLASSERT(nret);//组装接收数据包,发送到处理模块处理
}
m_pDataHandle->m_pDataMng->m_resp_LOGOUT = oLogout;
//MessageBox(NULL,oLogout.Description,"提醒",MB_OK);
m_pDataHandle->HandleNetCmdRecv(UMSG_LOGOUT);
}
void CMessageMng::HandleRespHeartbeat( void* pData )
{
NetDataItem* pItem = (NetDataItem*)pData;
st_resp_CLIENTHEARTBEAT oHeartbeat;
if (pItem->nMsgStatus == -1)//发送超时
{
m_nLostHeartbeatTimes++;
}
else if (pItem->nMsgStatus == -2)//接收超时
{
m_nLostHeartbeatTimes++;
}
else if (pItem->nMsgStatus == 2)//接收成功//处理消息
{
char* pInData = pItem->pDataRecv;
int nret = m_pXml2Data->UnpackegeHeartbeatResponse(pInData,oHeartbeat);
ATLASSERT(nret==0);//组装接收数据包,发送到处理模块处理
m_nLostHeartbeatTimes = 0;
}
//else if (rItem.nMsgStatus == 1 && rItem.nSimplex == 1)//收到事件并确认
//{
// //rItem.nSimplex == 1;//用不着接收
//}
if(m_nLostHeartbeatTimes > 3)
{
MessageBox(NULL,"心跳丢失","提醒",MB_OK);
m_pDataHandle->HandleNetCmdRecv(UMSG_LOGOUT);//要求退出
}
}
2、更改为简单的处理,简单明了
void CMessageMng::HandleNetItem(NetDataItem& rItem)
{
switch(rItem.nMsgId)
{
case UMSG_LOGIN:
HandleRespLogin(rItem);
break;
case UMSG_LOGOUT:
HandleRespLogout(rItem);
break;
case UMSG_CLIENTHEARTBEAT:
HandleRespHeartbeat(rItem);
break;
...
}
...
}
void HandleRespLogin(NetDataItem& rItem);
void HandleRespLogout(NetDataItem& rItem);
void HandleRespHeartbeat(NetDataItem& rItem);
总结:
在程序中最好不要使用那些特殊的复杂技巧,简单方法对人对己都是最好的方法。