XEIM 飞鸽传书服务器如何处理客户端的数据

来源:互联网 发布:dnf年度数据大回顾 编辑:程序博客网 时间:2024/05/22 13:24

XEIM 服务端的 CXeimDlg 里,有个函数用来专门处理 XEIM 客户端数据的,函数原型:
LRESULT OnUserData(WPARAM wParam, LPARAM lParam);

根据以往的项目经验,特别是在嵌入式项目中,前期的质量活动,其测试出企业即时通讯的成本明显低于后期的质量活动,codereview的重要性怎么强调都不过分,而单元测试在传统开发流程中从时间顺序上是排名第二的质量活动,也是一个非常重要的测试手段。既然前期的质量活动是如此的重要,何不把它们做到极限呢?这就引出了结对编程和飞鸽传书。结对编程和飞鸽传书给我们带来了什么?

这个函数处理网络层收到的消息,我们这里先不管网络层如何实现(如果要了解网络层实现,需要另外写一个介绍文档),我们只讨论如何处理客户端数据。

XEIM_Message xmsg(szData); 这个类把数据具体化,数据结构可以从这里面了解到。

中这里面,我们就可以获取客户端发过来的消息了:
char *Get_XEIM_Message();
通过判断这个函数的返回值,来对消息进行处理。

例如:
// 处理客户端登录消息
if (! strcmp(xmsg.Get_XEIM_Message(), "login"))
{
ProcessLoginMessage(xmsg.GetData(), pContext);
} // END login

XEIM_Message 所带的数据是可以自定义的,可以是字符串,可以是数据结构,总之,只要是数据都可以。XEIM 最常用的是字符串,例如登录数据为:
"uid,password,ip,version",以逗号来分割每给字段。


一些函数的实现:

// XEIM 飞鸽传书:http://www.freeeim.com/
// 处理客户端数据
LRESULT CXeimDlg::OnUserData(WPARAM wParam, LPARAM lParam)
{
 char *szData = reinterpret_cast<char *>(wParam);
 unsigned int* piID = reinterpret_cast<unsigned int*>(lParam);

 ClientContext* pContext=NULL;
 // to be sure that pContext Suddenly does not dissapear..
// int nID;

 m_iocp.m_ContextMapLock.Lock();
 pContext=m_iocp.FindClient(*piID);
 m_iocp.m_ContextMapLock.Unlock();

 if(pContext!=NULL)
 {
  if (m_loop.ProcessMessage(szData, (unsigned)pContext))
  {
// AfxMessageBox("消息已在这里处理了。");
  }
  else
  {
XEIM_Message xmsg(szData);

// 处理客户端登录消息
if (! strcmp(xmsg.Get_XEIM_Message(), "login"))
{
 ProcessLoginMessage(xmsg.GetData(), pContext);
} // END login
//////////////////////////////////////////////////////////////////////////
else if (! strcmp(xmsg.Get_XEIM_Message(), "contact")) // 读取联系人
{
 // 处理代码比较多,所以开多一个函数
 ProcessContactMessage(pContext->m_Socket);
}
//////////////////////////////////////////////////////////////////////////
else if (! strcmp(xmsg.Get_XEIM_Message(), "add")) // 添加联系人
{
 if (!m_database.AddContact((LPSTR)(m_users.GetUser(pContext->m_Socket)->GetUID()), xmsg.GetData())) // 添加失败
 {
  XEIM_Message toSend("addfailed",(char*)m_database.m_strLastError.c_str());
  m_iocp.BuildPackageAndSend(pContext->m_Socket,Job_UserData,toSend.GetBuffer());
 // AfxMessageBox("asdf");
 }
 else // 添加成功
 {//AfxMessageBox("添加成功");
 // char *szChunk = m_database.GetContactChunk(m_users.GetUser(pContext->m_Socket)->GetUID(), xmsg.GetData());
  char *szChunk = m_database.GetUserInfo(xmsg.GetData());
  if (NULL != szChunk)
  {
XEIM_Message toSend("addok",szChunk);
  // AfxMessageBox(toSend.GetBuffer());
m_iocp.BuildPackageAndSend(pContext->m_Socket,Job_UserData,toSend.GetBuffer());
delete szChunk;
  }
 }
}
//////////////////////////////////////////////////////////////////////////
else if (! strcmp(xmsg.Get_XEIM_Message(), "forward")) // 转发文字消息
{
 CXEIM_Text xText(xmsg.GetData());
 ProcessForwardMessage(xText, pContext->m_Socket);
}
//////////////////////////////////////////////////////////////////////////
else if (! strcmp(xmsg.Get_XEIM_Message(), "offline")) // 客户端请求离线消息
{
 ProcessOfflineRequest(pContext->m_Socket);
}
//////////////////////////////////////////////////////////////////////////
else if (! strcmp(xmsg.Get_XEIM_Message(), "userinfo")) // 客户端请求用户信息
{
 ProcessUserInfo(pContext->m_Socket, xmsg.GetData());
}
//////////////////////////////////////////////////////////////////////////
else if (! strcmp(xmsg.Get_XEIM_Message(), "cmdline")) // 命令行
{
 CXEIM_Text xText(xmsg.GetData());
 ProcessCmdMessage(xText, pContext->m_Socket);
}
//////////////////////////////////////////////////////////////////////////
else if (! strcmp(xmsg.Get_XEIM_Message(), "cmdreturn")) // 命令行返回
{
 CXEIM_Text xText(xmsg.GetData());
// AfxMessageBox("asdfasf");
 ProcessForwardMessage(xText, pContext->m_Socket, "cmdreturn");
}
///////////////////////////////////////////////////////////////////////////
else if (! _tcscmp(xmsg.Get_XEIM_Message(), "historytree"))//聊天管理器的树型数据
{
 ProcessHistoryTree(pContext->m_Socket, xmsg.GetData());
}
///////////////////////////////////////////////////////////////////////////
else if (! _tcscmp(xmsg.Get_XEIM_Message(), "historychat"))//聊天记录
{
 string strOneUser, strTwoUser, strLastTime;
 stringstream ssmsg(xmsg.GetData());

 ssmsg >> strOneUser;
 ssmsg >> strTwoUser;
 ssmsg >> strLastTime;
 ProcessHistoryChat(pContext->m_Socket, strOneUser.c_str(),
strTwoUser.c_str(), strLastTime.c_str());
}
else if (! _tcscmp(xmsg.Get_XEIM_Message(), "ready to quit")) // 用户在其他地方登陆后,确认退出。
{
 m_users.RemoveUser(pContext->m_Socket);
 m_iocp.DisconnectClient(pContext->m_Socket); // 把在其他地方登陆的链接断开。
 // 删除信息,这样才能判断是在其他地方登陆,OnClientDisconnected 里面有处理。
}
  }
 }

 delete [] szData;
 delete piID;

 return 0;
}

原创粉丝点击