一个线程+ 一个查询问题

ccnyou 2013-05-22 10:55:45
最近在基于做个C/S即时聊天的东西,遇到觉得是两个比较棘手的问题:
先说服务端的查询的问题吧,由于服务端是根据socket识别客户端的,
而一个用户有几种属性,最基本就是用户名(唯一不变)和昵称(可修改)了。
一般来说服务端需要处理几种事件:
1,某用户登录,获取到用户名,昵称信息,还有对应的一个socket
2,某用户请求修改他的昵称或者其他信息
3,将消息发送给指定用户名的的用户(消息可能是管理员发送,也可能来自其他用户)
4,某用户下线了
5,也是最麻烦的。服务端中的列表控件根据管理员的拖动,需要重绘index从x到y的用户信息(譬如进度条在中间,而且这几个用户信息发生了变动,就需要重绘)。
为了能够尽快响应用户请求,我用了个哈希表将socket与用户名绑定了起来,酱紫的话可以迅速从socket
找到需要对应的用户,但是有个问题就麻烦了,当需要按照index(上线的先后顺序)查找用户时候,哈希表就力不从心了。这个不知道大家什么想法,可以分享下。

另一方面,客户端遇到的问题。客户端一个UI界面,一个维护网络连接的线程。网络连接作为单体对象存在。
在连接服务器的时候,我这边是酱紫:

do
{
try
{
//尝试连接
sharedConnection.ConnectToServer();
}
catch(...)
{
//发生了异常,模拟QQ的断线自动重连
cout << "连接发生了异常,2 分钟后重连"
Sleep(2*60*1000);
}
}while(this->m_shouldExit == false);//还不需要退出,继续尝试连接

酱紫的话,在用户退出或者客户端需要手动重连的时候会出现问题。
理想情况下,我不希望杀掉线程,希望它正常结束,酱紫能有效避免内存泄漏等问题。那么在退出客户端或者手动重连
的时候,我会sharedConnection.Disconnect()一次(m_shouldExit置true),
然后等待上一个连接的线程结束(WaitForSingleObject),以方便我重开线程。
但是,如果上个线程死在 Sleep(2*60*1000); 上面,那么我的WaitForSingleObject将不得不
等待2分钟。这个无论是对关闭客户端还是手动重连,都是客户无法接受的。
现在我的做法是在Sleep中加个for循环,每次Sleep(500),然后检查下m_shouldExit,决定是不是要退出
但是觉得做法太猥琐,不知道有没有更好的解决方案。
谢谢大家


...全文
110 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq120848369 2013-05-22
  • 打赏
  • 举报
回复
引用 4 楼 ccnyou 的回复:
[quote=引用 2 楼 qq120848369 的回复:] 另外一个线程一个连接的做法你还是学点高级技术吧, 要么select,要么iocp,这些在win32上支持的都很到位。
开线程是客户端的做法哦,客户端我也是在select的,但是select也是会阻塞的,所以还是开了线程的[/quote] 那你还是没学到家,是不是, 给你个链接:http://blog.csdn.net/CharlesPrince/article/details/1490932,wsaselect都提供基于消息机制的了,你还能阻塞你就厉害了。 一个连接一个线程是肯定不靠谱的,尤其是在win32上。
ccnyou 2013-05-22
  • 打赏
  • 举报
回复
引用 2 楼 qq120848369 的回复:
另外一个线程一个连接的做法你还是学点高级技术吧, 要么select,要么iocp,这些在win32上支持的都很到位。
开线程是客户端的做法哦,客户端我也是在select的,但是select也是会阻塞的,所以还是开了线程的
ccnyou 2013-05-22
  • 打赏
  • 举报
回复
引用 1 楼 qq120848369 的回复:
session *里维护next,prev做成链表,上线后追加到链表末尾。 另外维护socket->session*映射,用socket拿到session*, 可以直接从链表中移掉session*这个node而不影响用户上线顺序。 遍历在线用户就是遍历链表。
如果单纯是遍历自然没有问题,问题是,列表控件重绘的时候,是绘制到哪个单元格再请求那个对应单元格的数据的。例如在主对话框类实现函数 OnListCtrlGetTextForIndex(int rowIndex, int colIndex); 当列表控件需要数据就会调用这个接口。 那么它需要[5,10]这个区间的数据,他会调用5 * colCount次,我得在这里拿到数据返回给他,链表遍历的话 酱紫时间就到了n^3了
qq120848369 2013-05-22
  • 打赏
  • 举报
回复
另外一个线程一个连接的做法你还是学点高级技术吧, 要么select,要么iocp,这些在win32上支持的都很到位。
qq120848369 2013-05-22
  • 打赏
  • 举报
回复
session *里维护next,prev做成链表,上线后追加到链表末尾。 另外维护socket->session*映射,用socket拿到session*, 可以直接从链表中移掉session*这个node而不影响用户上线顺序。 遍历在线用户就是遍历链表。
ccnyou 2013-05-22
  • 打赏
  • 举报
回复
引用 5 楼 qq120848369 的回复:
[quote=引用 4 楼 ccnyou 的回复:] [quote=引用 2 楼 qq120848369 的回复:] 另外一个线程一个连接的做法你还是学点高级技术吧, 要么select,要么iocp,这些在win32上支持的都很到位。
开线程是客户端的做法哦,客户端我也是在select的,但是select也是会阻塞的,所以还是开了线程的[/quote] 那你还是没学到家,是不是, 给你个链接:http://blog.csdn.net/CharlesPrince/article/details/1490932,wsaselect都提供基于消息机制的了,你还能阻塞你就厉害了。 一个连接一个线程是肯定不靠谱的,尤其是在win32上。 [/quote] 版主大人别刷我啦,要不要我贴代码上来给你看?我并没有说一个连接一个线程,服务端我是CAnsycSocket实现的,客户端是自己封装的,是基于委托机制(类似消息机制)实现的。一个连接一个线程傻瓜都知道多几个连接就死了

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧