基于Java NIO的即时聊天服务器雏形
前不久自己动手写了一个Android的聊天工具,跟服务器的交互还是基于HTTP方式的,在一般通讯上还算凑活,但是在即时聊天的时候就有点恶心了,客户端开启Service每隔3秒去询问服务器是否有自己的新消息(当然3秒有点太快了),在心疼性能和流量的前提下,只能自己动手写个服务器,传统的Socket是阻塞的,这样的话服务器对每个Socket都需要建立一个线程来操作,资源开销很大,而且线程多了直接会影响服务端的性能(曾经测试开了3000多个线程就不让创建了,所以并发数目也是有限制的),听说从JDK1.5就多了个New IO,灰常不错的样子,找了找相关的资料,网上竟然全都是最最最简单的一个demo,然后去CSDN发帖,基本上都是建议直接使用MINA框架的,这样一来根本达不到学习NIO的目的,而且现在的技术也太快餐了,只知道使用前辈留下的东西,知其然不知其所以然。
折腾了一个周,终于搞出来了一个雏形,相比于xmpp的xml,本人更喜欢json的简洁,为了防止客户端异常断开等,准备采用心跳检测的机制来判断用户是否在线,另外还有一种方法是学习例如Tomcat等Servlet中间件的方式,设置Session周期,定时清除过期Session。本Demo暂时实现了Session过期检测,心跳检测有空再搞,如果本例子在使用过程中有性能漏洞或者什么bug请及时通知我,谢谢
?
一开始把文章发博客园了,结果发现Java基本成悲剧了,还是回JavaEye吧……
?
废话不多说,关于NIO的SelectionKey、Selector、Channel网上的介绍例子都很多,直接上代码:
?
1 public class Task { 2 public void checkState() { 3 Set<String> keys = SessionManager.getSessionKeys(); 4 if(keys.size() == 0) { 5 return; 6 } 7 List<String> removes = new ArrayList<String>(); 8 Iterator<String> iterator = keys.iterator(); 9 String key = null;10 while(iterator.hasNext()) {11 key = iterator.next();12 if(!SessionManager.getSession(key).isKeekAlive()) {13 removes.add(key);14 }15 }16 if(removes.size() > 0) {17 Log.i("sessions is time out,remove " + removes.size() + "session");18 }19 SessionManager.remove(removes.toArray(new String[removes.size()]));20 }21 22 public void sendAck() {23 Set<String> keys = SessionManager.getSessionKeys();24 if(keys.size() == 0) {25 return;26 }27 Iterator<String> iterator = keys.iterator();28 while(iterator.hasNext()) {29 iterator.next();30 //TODO 发送心跳包31 }32 }33 }
?
注意,在Task和SessionProcessor类里都有对SessionManager的sessions做遍历,文中使用的方法并不是很好,主要是效率问题,推荐使用遍历Entry的方式来获取Key和Value,
因为一直在JavaWeb上折腾,所以会的童鞋看到Request和Response会挺亲切,这个例子没有经过任何安全和性能测试,如果需要放到生产环境上得话请先自行做测试- -!
?
客户端请求时的数据内容例如{handler:"UserHandler",action:"login",imei:"2364656512636".......},这些约定就自己来定了
?
代码在家里的机器上,回去补上,请各位大大指证 - -!
?