锁定老帖子 主题:AJAX 反推技术的一点疑问
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-09-13
最后修改:2011-09-13
看看这个吧,一般是使用comet实现的。
http://en.wikipedia.org/wiki/Comet_%28programming%29 |
|
返回顶楼 | |
发表时间:2011-09-13
最后修改:2011-09-13
squll369 写道 axiheyhey 写道 ajax反推技术并非真正意义上的服务器推,只是一个模拟。主要是基于HTTP长连接
相关介绍:http://www.ibm.com/developerworks/cn/web/wa-lo-comet/ 长连接看了这个,有点了解了,轮询可否再指点一下? 上面的链接都介绍了啊。。long-polling和streaming,两者都属于长连接。。 1. long-polling就是轮询,客户端发起一个请求,服务器阻塞请求,直到有新的消息或超时后返回一个respone,客户端再收到respone后继续发起一个请求,如此循环。优点是服务器负担较小,缺点是即时性较差。 2. stream一般是通于隐藏iframe,这个iframe向服务器发起一个请求,服务器会一直保持这个请求直接超时或通信出错,期间一旦有数据,客户端就会接收到,有点像是浏览器向服务器请求一个永远也下不完的文件一样。这种方式即时性更高,缺点是我们看到的页面一直会处于加载状态,服务器负担大。 |
|
返回顶楼 | |
发表时间:2011-09-14
这两种方式一直保留着实体网络连接,一旦客户端数量比较多的时候,感觉会对web服务器的服务能力有比较大的影响
|
|
返回顶楼 | |
发表时间:2011-09-14
tsoukw 写道 这两种方式一直保留着实体网络连接,一旦客户端数量比较多的时候,感觉会对web服务器的服务能力有比较大的影响
+1 |
|
返回顶楼 | |
发表时间:2011-09-15
我的博客上用的是long-polling,已经抛弃这个东东了,呵呵。
|
|
返回顶楼 | |
发表时间:2011-09-15
最后修改:2011-09-15
axiheyhey 写道 ajax反推技术并非真正意义上的服务器推,只是一个模拟。
1. long-polling就是轮询,客户端发起一个请求,服务器阻塞请求,直到有新的消息或超时后返回一个respone,客户端再收到respone后继续发起一个请求,如此循环。优点是服务器负担较小,缺点是即时性较差。 基于这个,我写了一个demo: 在客户端我写了一个请求,在页面load的时候发起,去我定义的onlineinfo这个servlet去后台请求,readyState 为3的时候,我获取数据,readyState为4的时候,请求结束,我重新发起请求。 function loadOnlineInfo(){ var req = initXMLHTTPRequest(); url = 'http://127.0.0.1:8080/demo/' + '/onlineinfo'; if(req){ req.onreadystatechange = onReadyStage; req.open("POST",url,true); req.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); req.send(); } } function onReadyStage(){ var ready=this.readyState; if(ready==1){ }else if(ready==2){ }else if(ready==3){ onlineInfo = this.responseText; if(onlineInfo){ //do front logic } }else{ //re-create request loadOnlineInfo(); } } 在onlineinfo这个servlet里,我阻塞请求,代码如下: int onlineNums = OnlineUserHolder.getOnlineUsers().size(); User user = (User)req.getSession().getAttribute(ELSConstant.KEY_SESSION_USER); //Block Server while(OnlineUserHolder.getOnlineUsers().size() == onlineNums){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } logger.debug("[" + user.getLoginName() + "] Still waitting new user login..."); } 。。。。。 out.write(json.toString()); 。。。。。 OnlineUserHolder这个类,我定义了,当前用户的在线信息,OnlineUserHolder.getOnlineUsers().size()可以获得当前用户的在线数,如果有变化,就推出循环阻塞,返回数据给前台。 这样的Demo出来以后,我使用了一下,发现是可以达到我要的效果,当别人登陆的时候,自己的页面会立刻显示出该用户上线了,而不用刷新页面。 但是还有几个问题: 1 在页面load的时候发起请求,也就是说,这个页面一刷新,就发一个请求到后台,被后台阻塞着,也就是说,后台服务的一个线程就阻塞在那里,如果刷新了好多次页面,那不就开了好多个线程,而且,用户有可能转到其他的页面,这个线程的返回对他来说也没有意义了,那有什么好的解决方案吗? 比如,对一个sessionid + userid只开一个请求? 2.好像是线程安全的问题,这个demo对于 相互登陆有bug. 比如A用户登陆,在这个页面上观察,然后B用户登陆了,在A用户的页面上,B用户登陆的状况会立刻显示出来,然后B用户注销,B用户注销的状况也会立刻显示出来。 但是反之,如果A用户登陆,然后B用户登陆了,A用户注销,在B用户的页面上,就不会显出出A用户注销的状况。我还用研究一下,这个问题,有人能大概估计一下是什么问题吗? |
|
返回顶楼 | |
发表时间:2011-09-15
squll369 写道 但是还有几个问题: 1 在页面load的时候发起请求,也就是说,这个页面一刷新,就发一个请求到后台,被后台阻塞着,也就是说,后台服务的一个线程就阻塞在那里,如果刷新了好多次页面,那不就开了好多个线程,而且,用户有可能转到其他的页面,这个线程的返回对他来说也没有意义了,那有什么好的解决方案吗? 比如,对一个sessionid + userid只开一个请求? 2.好像是线程安全的问题,这个demo对于 相互登陆有bug. 比如A用户登陆,在这个页面上观察,然后B用户登陆了,在A用户的页面上,B用户登陆的状况会立刻显示出来,然后B用户注销,B用户注销的状况也会立刻显示出来。 但是反之,如果A用户登陆,然后B用户登陆了,A用户注销,在B用户的页面上,就不会显出出A用户注销的状况。我还用研究一下,这个问题,有人能大概估计一下是什么问题吗? 今天头有点沉,懒得看你的code了。。关于你的第一个问题是现实存在的,所以才会有bayeux之类的协议产生来解决这类问题。关于第二个问题,因为我没看你的code,所以我只能说可能是。。应该是。。你的实现有点瑕疵。 |
|
返回顶楼 | |
发表时间:2011-09-15
OK,
我加了一个List<String> sessionIdwithUserId = new ArrayList<String>();这2个问题都解决了! 在loop阻塞前, User user=(User)req.getSession().getAttribute(ELSConstant.KEY_SESSION_USER); String sessionwithUserid = req.getSession().getId() + "-" + user.getUserId(); if(checkSessionIdWithUserId(sessionIdwithUserId, sessionwithUserid)){ return; }else{ sessionIdwithUserId.add(sessionwithUserid); } 然后阻塞一结束,remove掉 //remove sessionidWithuserid sessionIdwithUserId.remove(sessionwithUserid); 本来是想解决第一个问题的,试验下来,第2个问题也解决了。。。还要再分析分析。赫赫,谢谢了! 做了一个练习,终于算对这个反推,小有理解了。 |
|
返回顶楼 | |
发表时间:2011-09-19
我一直奇怪!
|
|
返回顶楼 | |
发表时间:2011-10-13
我们用的是nodejs+socket.io
缺点是稳定性稍差,学习成本比较高,还有和现有系统的对接。 |
|
返回顶楼 | |