当前访客身份:游客 [ 登录  | 注册加入尚学堂]
直播

我来了!

拥有积分:3972
尚学堂雄起!!威武。。。

博客分类

笔记中心

课题中心

提问中心

答题中心

解答题中心

漫扯:从polling到Websocket

我来了! 发表于 2年前 (2014-11-03 09:43:49)  |  评论(0)  |  阅读次数(464)| 0 人收藏此文章,   我要收藏   

Http被设计成了一个单向的通信的协议,即客户端发起一个request,然后服务器回应一个response。这让服务器很为恼火:我特么才是老大,我居然不能给小弟发消息。。。

轮询

  老大发火了,小弟们自然不能无动于衷,为了能及时获得老大的消息,小弟们只好每隔一段时间跑去老大那里问问,有没有新的指示发出。这便是最早实现实时获得服务器数据的技术轮询(Polling

  客户端通过ajax不停去向服务器获得数据,检查是否有新的数据更新。这种使用轮询实现一种伪实时的状态很容易,但效率偏低,一般而言,这种实时获得的数据,本身数据量不是非常大,而通过这种反复地发起request的方式,往往造成的可能是httpheader信息比数据本身还多,而且大多数时候获得的数据都是重复无用的。据说最早还有通过不断刷新客户端页面,来实现web实时通信的情况~ 我想应该木有哪个客户会受得了这种体验。

Comet

  不值啊!咱哥几个每天跑来跑去。拿到的都是一堆没用的数据。

 

  于是大家坐在一起想,有什么好办法能不用老是跑腿又可以获得新的信息及时行动呢?小的们灵机一动,下次我们跑去老大那里等着,等他老人家下了命令再回来。这就是基于 AJAX 的长轮询(long-polling)方式实现的一种comet方式。因为ajax的调用是异步的,我们可以在页面加载完毕之后,发起一个request请求,服务器端会阻塞request直到有数据传递或超时(timeout)才返回。客户端处理完服务器返回的信息后,再次发出请求,重新建立连接。这样周而复始。

  基于 AJAX long-polling

  另外还有一种comet模型,他的名字玄乎比长轮询邪乎的多。。。叫The forever iframe technique这名儿听起来就高大上很多。其实就是在页面中隐藏一个iframe标签,然后将这个iframeSRC 属性设为对一个长连接的请求,服务器端就能源源不断地往客户端输入数据。但是这种方法有一个很明显的问题,各个浏览器会一直显示页面加载没有完成,如果用户是个强迫症,他一定会分分钟关掉页面的。TAT......

 forever iframe技术

 

  不管怎么样comet技术第一次实现了真正的实时通信,而且能支持大量用户,小的们从此总是能准确地获得老大的消息了。但是comet不会是一个没有副作用的解决方案,由于长期占用连接,web丧失了无状态高并发的特点,大量消耗了服务器带宽和资源。

WebSocket登场

  “跑来跑去真是麻烦诶~http肿么这么麻烦呀。咱们和老大之间整个新协议吧。”  

  这个想法在小弟们中炸开了锅!!! 在大家的千呼万唤中,WebSocket协议登场了。哈哈哈哈哈~让我来拯救各位吧~~~~

  WebSocket协议是HTML5定义的一种新协议,它实现了浏览器与服务器全双工通信(full-duplex)。通过浏览器发出websocket连线请求,然后服务器发出回应,建立一个联系的通道。小的们只用发个信息问老大:“首长好~”,老大回一个信儿:“同志们辛苦了!”这样握手(handshaking)就完成了,websocket连线完成,通过websocket,我们可以完成真正的实时通信了。

  websocket允许通过JavaScript建立与远程服务器的连接,从而实现客户端与服务器间双向的通信。在websocket中有两个方法:  

    1send() 向远程服务器发送数据

    2close() 关闭该websocket链接

  websocket同时还定义了几个监听函数    

    1、onopen 当网络连接建立时触发该事件

    2、onerror 当网络发生错误时触发该事件

    3、onclose websocket被关闭时触发该事件

    4、onmessage websocket接收到服务器发来的消息的时触发的事件,也是通信中最重要的一个监听事件。

  websocket还定义了一个readyState属性,这个属性可以返回websocket所处的状态:

    1CONNECTING(0) websocket正尝试与服务器建立连接

    2OPEN(1) websocket与服务器已经建立连接

    3CLOSING(2) websocket正在关闭与服务器的连接

    4CLOSED(3) websocket已经关闭了与服务器的连接

  websocketurl开头是ws,如果需要ssl加密可以使用wss,当我们调用websocket的构造方法构建一个websocket对象(new WebSocket(url))的之后,就可以进行即时通信了。

  

  哈哈哈哈哈哈~老大通过websocket发话了:

    晚上请吃饭!

  小弟们赶紧行动起来~

总结

  相比comet技术,websocket不仅节约了header的问题(websockethead信息只有短短的2个字节)。更加重要的是是通信的稳定性,comet在遇到网络问题之后,想要在不刷新页面的情况下恢复通信,非常困难,而websocket中提供了onclose函数来处理断开网络后的情况,这为我们与服务器的通信提供了可靠的保障。在github上有一个js库(https://github.com/joewalnes/reconnecting-websocket)就是通过这种方式来处理websocket断网重连。

  websocket看起来广泛实现只是时间问题了,当然这么好用的websocket也不是没有它的问题,websocket目前来看最大的问题是浏览器的支持(幸好大部分的服务器软件在比较新的版本中都已经支持了websocketie直到10才开始支持这种协议,而且每个浏览器最近在升级浏览器的时候,都会对websocket做出细微的调整。而且,想象你打开一个页面,当这个页面打开websocket连接并且执行一个内部IP地址的端口扫描,如果端口扫描发现了内部网络上发现了一个开启的80端口,一个隧道就可能通过你的浏览器建立。这样做很可能最终绕过防火墙,并且允许访问内部内容。所以安全问题,也是websocket现在面临的一大隐患。

分享到:0
关注微信,跟着我们扩展技术视野。每天推送IT新技术文章,每周聚焦一门新技术。微信二维码如下:
微信公众账号:尚学堂(微信号:bjsxt-java)
北京总部地址:北京市海淀区西三旗桥东建材城西路85号神州科技园B座三层尚学堂 咨询电话:400-009-1906 010-56233821
Copyright 2007-2015 北京尚学堂科技有限公司 京ICP备13018289号-1 京公网安备11010802015183