这次来个有界面的。

  登录界面:

  主界面:

1、服务端开发:

  只需创建一个类ChatType(./examples/HelloKhala/src/ChatType.cpp),在该类型中,核心为创建的两个消息事件,一个为onCurrFriends,用于获取当前在线用户;一个为onSendMsg,用于向具体用户发送消息。

  客户端请求当前的在线用户的信息,发送请求消息。该请求消息由onCurrFriends解析。onCurrFriends首先获取所有类型为ChatType的在线用户的id,然后再遍历这些id,根据id获取具体的用户信息,并将这些信息以json形式进行处理,设置类型为CHAT_TYPE,并最终将该json消息发送给请求的客户端。

bool ChatType::onCurrFriends(khala::InfoNodePtr& infoNodePtr, Json::Value& msg,
khala::Timestamp time) {
Json::Value res;
//返回给请求用户的消息类型
res[MSG_TYPE] = CHAT_FRIENDS;
res["result"] = "true";
khala::NodeManager* nodeManager = getNodeManager();
//获取类型为ChatType的在线用户的id
std::vector<uint> currIds = nodeManager->getNodeIDs(
infoNodePtr->getNodeType());
for (std::vector<uint>::iterator it = currIds.begin(); it != currIds.end();
++it) {
khala::InfoNodePtr usrInfoNode;
//根据id获取具体用户的信息
if (nodeManager->find(*it, usrInfoNode)) {
Json::Value usrJs;
usrJs[KEY_ID] = *it;
UsrInfo* usrInfo = boost::any_cast<UsrInfo*>(
usrInfoNode->getExtraContext());
usrJs["name"] = usrInfo->getName();
res["data"].append(usrJs);
}
}
//发送json消息
Json::FastWriter jwriter;
std::string sendStr = jwriter.write(res);
infoNodePtr->send(sendStr);
return true;
}

  客户端用户A请求发送消息msg给用户B,该请求消息由onSendMsg解析。onSendMsg获取消息msg,根据用户B的id获取用户B的对象,并将msg以json进行消息处理后设置消息类型为CHAT_REV,并发送给用户B。同时记录发送结果,并将结果以json形式进行处理,最后设置消息类型为CHAT_SEND将该结果返回给用户A。

bool ChatType::onSendMsg(khala::InfoNodePtr& infoNodePtr, Json::Value& msg,
khala::Timestamp time) {
Json::Value res;
//返回给请求发送用户的消息类型
res[MSG_TYPE] = CHAT_SEND;
//获取目的用户的id
uint friendId = msg[KEY_FRIEND_ID].asUInt();
//得到待发送消息
std::string sendMsg = msg[CHAT_MSG].asString();
res[FRIEND_NAME] = msg[FRIEND_NAME].asString();
res[CHAT_MSG] = sendMsg;
khala::InfoNodePtr friendNodePtr;
//根据目的用户的id获取目的用户的对象
if (this->getNodeManager()->find(friendId, friendNodePtr)) {
Json::Value sendJs;
//发送给目的用户的消息类型
sendJs[MSG_TYPE] = CHAT_REV;
//发送给目的用户的消息
sendJs[CHAT_MSG] = sendMsg;
UsrInfo* usrInfo = boost::any_cast<UsrInfo*>(
infoNodePtr->getExtraContext());
if (usrInfo == ) {
return false;
}
//发送用户的姓名和id
sendJs[SEND_NAME] = usrInfo->getName();
sendJs[KEY_FRIEND_ID] = infoNodePtr->getId();
//将该json消息发送给目的用户
Json::FastWriter jwriter;
std::string sendStr = jwriter.write(sendJs);
friendNodePtr->send(sendStr);
//向请求用户标示结果为成功
res["result"] = "true";
} else {
//向请求用户标示结果为失败
res["result"] = "false";
}
//将发送结果返回给请求用户
Json::FastWriter jwriter;
std::string sendStr = jwriter.write(res);
infoNodePtr->send(sendStr);
return true;
}

2、客户端开发:

  主要工作,拖界面,写控件响应事件!(废话)

  主要创建2个线程,一个为消息发送线程,一个为消息接收线程。

  消息发送线程:建立一个多生产者单消费者模型,每个窗口作为一个生产者,消息发送线程作为单独的消费者,选择System.Collections.Queue作为中间缓存。窗口将待发送json消息通过生产者接口发送给缓存容器。一旦缓存容器中存在待发送的消息,发送线程便被唤醒,从缓存中读取消息,对消息进行处理(选择utf8对字符进行处理,并添加长度头解决粘包问题),最终通过套接字发送给服务端。

  消息接收线程:以阻塞方式通过套接字循环接收消息,并将消息以字节形式保存在接收缓存中,通过长度头从接收缓存中获取每条完整的消息。再对该消息进行字符处理,解析为json形式,并根据消息类型将完整的消息通过SendMessage()发送给相应的窗口句柄进行处理。

  在每个具体窗口中,通过重写DefWndProc()来获取接收线程获取到的具体消息,并根据接收到的json消息编写窗口响应函数。

  具体客户端的代码就不贴了,不会C#,代码写得丑…

  最近应该会重写设备生命周期部分的代码,之前生命周期的超时检测部分设计实现得太丑陋,自己都看不下去了。争取少改动主要接口吧,阿门...

9、Khala实现0.01版QQ的更多相关文章

  1. KmdKit4D 0.01正式版发布了(0.02版已放出)(Delphi做驱动)

    此版本较0.01预览版已经有了脱胎换骨的变化,主要表现在以下几个方面:    1.对程序的结构进行了调整,将原来的ntutils.dcu分成fcall.dcu.halfcall.dcu和macros. ...

  2. 【Android】Vitamio 4.0 正式版发布/ Vitamio IOS 测试版发布(2013-07-16)

    一.链接 Vitamio官网:http://www.vitamio.org/ 官网github地址:https://github.com/yixia 自己无法编译通过的这里下载: Vitamio 4. ...

  3. 【6年开源路】海王星给你好看!FineUI v4.0正式版暨《FineUI3to4一键升级工具》发布!

    去年10-28号,我发布了一篇文章<海王星给你好看!FineUI v4.0公测版发布暨<你找BUG我送书>活动开始>,标志着FineUI开始向4.0版本迈进.经过4个月3个公测 ...

  4. 微信小程序(原名微信应用号)开发工具0.9版安装教程

    微信小程序全称微信公众平台·小程序,原名微信公众平台·应用号(简称微信应用号) 声明 微信小程序开发工具类似于一个轻量级的IDE集成开发环境,目前仅开放给了少部分受微信官方邀请的人士(据说仅200个名 ...

  5. javascript版QQ在线聊天挂件

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. 微信5.0 Android版飞机大战破解无敌模式手记

    微信5.0 Android版飞机大战破解无敌模式手记 转载: http://www.blogjava.net/zh-weir/archive/2013/08/14/402821.html 微信5.0 ...

  7. 开放源代码的微微信.NET 0.8 版公布了

    微微信.NET 0.8 版公布了     A.源代码应用范围:         未认证的和经过认证的微信订阅号.微信服务号均可使用,本源代码的每个模块都提供全然的 ASP.NET C#源代码,绝对不含 ...

  8. Moon.Orm 5.0 (MQL版)

    Moon.Orm 5.0 (MQL版) 实战实例Moon.Orm 5.0 革命性的设计 打造最便捷的异步分页技术(提供下载) 摘要: 一.建一个项目(以WebForm为例)配置文件配置(注意您自己的路 ...

  9. QzzmServer v2.0正式版发布

                                 V2.1升级程序已发布,具体见下文                                首先,感谢网友的热情的测评及反馈,现Qzzm ...

随机推荐

  1. Maybe I go too extreme

    昨天拖着一个没睡好的身体去面试了2家公司 被问到Collection的子集的时候顿时傻了一会,明明很简单的问题一时就想不起来了,哈哈.果然做it的人身体要顾好,状态太差了. 发现了一个问题,其实也是早 ...

  2. java Eclipse debug技巧

    摘要:调试不仅可以查找到应用程序缺陷所在,还可以解决缺陷.对于Java程序员来说,他们不仅要学会如何在Eclipse里面开发像样的程序,更需要学会如何调试程序.本文介绍了Java程序员必知的10个调试 ...

  3. HDU 5195 - DZY Loves Topological Sorting

    题意: 删去K条边,使拓扑排序后序列字典序最大 分析: 因为我们要求最后的拓扑序列字典序最大,所以一定要贪心地将标号越大的点越早入队.我们定义点i的入度为di. 假设当前还能删去k条边,那么我们一定会 ...

  4. C语言中对于结构的定义一般放在.h中还是.c中

    单文件使用的结构体放.c文件中 本模块内部使用结构体,放模块内部头文件中 供外部使用的结构体,放模块对外头文件中.

  5. hibernate+spring+mvc+Easyui框架模式下使用grid++report的总结

    最近刚开始接触hibernate+spring+mvc+Easyui框架,也是刚开通了博客,希望能记录一下自己实践出来的东西,让其他人少走弯路. 转让正题,以个人浅薄的认识hibernate对于开发人 ...

  6. 开心菜鸟系列学习笔记-------javascript(3)

    一.原型链:     1)Object 是一个属性的集合,并且都拥有一个单独的原型对象.,这个原型对象object可以是一个object或者null值 2)不过一般来说,我们会使用__内部属性名__下 ...

  7. Could not open a connection to your authentication agent

    执行ssh-add ~/.ssh/rsa  就会遇到上述错误了 解决方案: 先执行  eval `ssh-agent`  (是-键上的那个`) 再执行 ssh-add ~/.ssh/rsa成功 ssh ...

  8. linux网址

    1. 上海爱墨电子科技有限公司 http://www.shaimo.cn/showproduct.asp?piccat_id=196&pic_id=780 2. http://lxr.free ...

  9. Java宝典(一)

    -switch语句能作用在byte上,能否作用在long上,能否作用在String上? -在switch(expr1)中,expr1只能是一个整数表达式或者枚举常量,整数表达式可以是int基本类型或I ...

  10. 《Algorithms 4th Edition》读书笔记——3.1 符号表(Elementary Symbol Tables)-Ⅰ

    3.1符号表 符号表最主要的目的就是将一个键和一个值联系起来.用例能够将一个键值对插入符号表并希望在之后能够从符号表的所有键值对中按照键值姐找到对应的值.要实现符号表,我们首先要定义其背后的数据结构, ...