客户端和服务端创建并保持一个长连接,在服务端就会相应的创建一个线程的方式缺憾讨论

流子
游戏开发领域优质创作者
博客专家认证
2008-08-28 09:21:20
下面是我和一网友在邮件组的一组对话,就是关于“是否客户端和服务端创建并保持一个长连接,在服务端就会相应的创建一个线程”的问题:
我们的意见如下:
A:当连接较少时,一个连接一个线程是可以接受的。但,网游的接入服务器连接都几千个,一个连接一个线程肯定不行。
Me:我觉得服务器端被客户端一个连接然后开一个线程是很合理的。否则,怎么实现啊
A:不是吧, 那要建多少个线程啊, 现在一般不都是完成端口模型吗, 多个连接共享一个线程。
me:太多 Thread 不合理的, 请求处理 Thread 和 数据处理 Thread 各一个.用数据队列和信号之类同步.
每个 client 一个Thread 不太好.除非用户量小.
A:如果一个长连接就一个线程 5000个线程 那不是电脑都挂了!
Me:
不会产生这种情况的,举个很简单的case,QQ游戏大厅玩过的吧,前面的Login server,大厅server,都是短连接,那就不说了,和房
间服务器保持长连接,看看每台房间服务器的上限人数:500,也就是说最多,最终和一台room server保持长连接的上限也就500,我觉得一个长连接开一个线程还是可以满足这种需求的。
A:每个server只负责一个room?这个结论从哪来的
Me:这不是结论,你完全可以这样设置,不过一台server有时候会有多个room,而这些room都是在不同的进程中,比如3个,4个,还是完全可以承受

A是对方,Me是我,我知道在windows下用iocp,在linux下使用epoll比起我目前的方式要好的多,但是我不知道Java中相应的有没有IOCP完成端口,epoll的模型,NIO是否和这两种方式有关?觉得目前我的这种实现方式也是满足需求的,下面是引自一篇文章上的话题,大家可以参考:
大多数的网络游戏的服务器都会选择非阻塞select这种结构,为什么呢?因为网络游戏的服务器需要处理的连接非常之多,并且大部分会选择在Linux/Unix下运行,那么为每个用户开一个线程实际上是很不划算的,一方面因为在Linux/Unix下的线程是用进程这么一个概念模拟出来的,比较消耗系统资源,另外除了I/O之外,每个线程基本上没有什么多余的需要并行的任务,而且网络游戏是互交性非常强的,所以线程间的同步会成为很麻烦的问题。由此一来,对于这种含有大量网络连接的单线程服务器,用阻塞显然是不现实的。

诚心请教,期待回复!谢谢!分数只有100分左右了,全都拿出来了,顺便弱弱的问一句:分数散光了哪里去赚快一点?哈哈

...全文
1055 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
冰思雨 2008-08-28
  • 打赏
  • 举报
回复
不赞成服务端,在TCP长连接的时候,一个客户端分配一个线程做终身维护。
1.线程没有得到充分的利用。
A。按时间配比来讲,线程阻塞时长所占的比例要绝对大于处理数据的时长。
B。系统会为每个线程分配内存资源(LZ也说了在Linux/Unix下的线程是用进程这么一个概念模拟出来的,比较消耗系统资源
2.线程数量超过某一数值时,会对系统的整体性能造成影响。(个人觉得这个峰值和服务器内存容量有关)
3.如果用阻塞方式来处理的话,对线程的可控性就不太好设计了。(比如,看哪个客户端连接不顺眼,要断开连接)


一条线程维护多个连接,具体使用哪些类,我还没有使用过。但是,推荐采用线程池技术来提高处理效率。
Java中类似IOCP,epoll的模型具体位置应该在java.nio.channels包下面,
着重查看Selector、SelectableChannel、SelectionKey、ServerSocketChannel和SocketChannel这几个类。
zhao_tk 2008-08-28
  • 打赏
  • 举报
回复
不懂,mark
ChDw 2008-08-28
  • 打赏
  • 举报
回复
一个用户一个线程 的确是 设计简单,实用


但是如果服务器要支持很大量的长连接也不行的,最好还是用一个或若干固定数量的专门线程读取客户端数据,然后再交由线程池处理请求
老紫竹 2008-08-28
  • 打赏
  • 举报
回复
为何要长连接?

对于邮件,可以最快速度的看到新的邮件,类似于邮件聊天,google的功能吧。

不过就算再快,如果不是群聊,我想2-5秒钟还是需要的吧。


我想还是服务器端做线程池比较合理,可以服务更多的客户请求。

不过对于长连接个人觉得,为了改善客户的感受,值得。一个用户一个线程,设计简单,实用,我认为比较好。
ChDw 2008-08-28
  • 打赏
  • 举报
回复
Java 已经提供了nio的支持,可以支持非阻塞的连接,你可以通过一个专门线程作为所有客户端读取数据的类

这个类在完整的读取了客户端请求后,在线程池中找一个空闲的线程,将客户端的请求交由这个空闲的线程执行


流子 2008-08-28
  • 打赏
  • 举报
回复
分析了一下,我目前用的是传统socket阻塞式通信:每建立一个Socket连接时,同时创建一个新线程对该Socket进行单独通信(采用阻塞的方式通信)。这种方式具有很高的响应速度,并且控制起来也很简单,在连接数较少的时候非常有效,但是如果对每一个连接都产生一个线程的无疑是对系统资源的一种浪费,如果连接数较多将会出现资源不足的情况

而NIO是一个基于事件的IO架构,最基本的思想就是:有事件我通知你,你再去做你的事情.而且NIO的主线程只有一个,不像传统的模型,需要多个线程以应对客户端请求,也减轻了JVM的工作量。

打算用MINA通讯框架把以前的设计改成NIO形式,但有人说“MINA解决的是高并发,小流量的数据传输,对于长连接大流量的网络游戏,QQ游戏平台, 似乎不大适合”我对他的观点有点怀疑,但没有实际的证据,不知各位怎么看?
zou_wei_forever 2008-08-28
  • 打赏
  • 举报
回复
mark!

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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