websocket初学总结
29 Aug 2017
上一周有空就研究了一下websocket
,我记得很久之前有一次面试被问到websocket
,不过当时我并不会,只是听说过有这么个东西,知识点太多了,如果说工作上不会用到的话,我并不着急着去学,更何况是比较新的,浏览器支持不是很全面的知识点呢,但是既然最近有空,于是就看了一下。
1.什么是websocket
websocket是一个网络协议,其最大的特点就是可以由服务端主动向客户端通信,客户端也可以向服务端发送消息,一种双向通信的解决方案。注意重点:双向
2.在websocket之前
聊websocket
之前,我们先来了解websocket
之前的相关技术。http
其中一个特点,就是通信只能由客户端主动向服务端发起请求(单向),如果要做一些实时类的,比如IM、聊天室,在没有websocket
之前,我们需要用其他的解决方案来处理。
1.短轮询(又叫轮询):通过定时器不断使用ajax向服务端请求数据;
像这样的对话:
(0:00)
客户端:喂,服务端,我有信息吗?
服务端:没有哦
(1:00)
客户端:喂,我有新的消息么?
服务端:没有哦
(2:00)
客户端:喂,我有新的消息么?
服务端:有啦,拿着
(3:00)
客户端:喂,我有新的消息么?
服务端:没有哦
……
缺点可想而知,轮询频率和更新时机都是一个影响连接效率和性能的问题,浪费带宽;
2.长轮询:其实跟短轮询有点像,都是ajax实现,只是这次是先ajax设置超时时间,后端挂起请求,当响应时,处理好响应后递归调用ajax,或当ajax请求达到超时时间时,重新递归ajax请求。
(0:00)
客户端:喂,服务端,我有信息吗?没有的话我就等着,有消息就告诉我
服务端静静的默不作声,因为没有消息,所以hold着连接
(1:00)
服务端:有消息来了,拿着。(ajax完毕)
客户端接到回答后,紧接着又:喂,服务端,我有信息吗?没有的话我就等着,有消息就告诉我
服务端静静的默不作声,因为没有消息,所以hold着连接
(2:00)
服务端:有消息来了,拿着。(ajax完毕)
客户端接到回答后,紧接着又:喂,服务端,我有信息吗?没有的话我就等着,有消息就告诉我
服务端静静的默不作声,因为没有消息,所以hold着连接
(3:00)
上一个连接超时了关闭了连接,于是
客户端:喂,服务端,我有信息吗?没有的话我就等着,有消息就告诉我
……
缺点:一直占着服务器资源连接。
3.流:从关于轮询实现参考资料来看,指的是长轮询的另一种基于iframe 或者htmlfile的流。具体可以到链接原文查看,这里不做讲述。
4.SSE Server-SentEvents(貌似只是接受服务端信息),这块我没深入研究
5.Flash 依赖flash,移动端支持不好,于是慢慢淡出
综上,各种方案都有着一定的缺点,尽管flash方案似乎挺好的,但奈何移动端支持不好,随着技术不断发展,便有了更好的websocket解决方案,简单来说websocket就是基于TCP的双向通信实时传输协议,它是基于事件的方式来做数据处理响应的,并且允许跨域。
3.websocket怎么用
websocket的简单原生使用:包括客户端和服务端
在浏览器端,会有一个WebSocket
的对象,通过new构造的方式来建立websocket连接,通过实例ws调用onopen
方法来监听连接建立事件,通过onmessage
来监听服务端分发消息事件,通过onclose
来监听关闭连接事件,通过send
方法来向服务端推送消息。示例如下:
客户端:(浏览器) 需要另外启动服务来承载这个页面
服务端:node
实现,可选用ws
先安装ws
然后写脚本
前面提到index.html
要启动一个服务来承载,当然也可以直接服务端脚本一同承载之
这样就能直接打开 http://127.0.0.1:10087
访问到index.html
了,并且页面能和服务端直接通信。不过对比前面index.html
独立承载的话,还能突出一个ws
可跨域的特点。
再细化的ws操作,可参考ws的github。
4.补充:socket.io 简易实践
接下来,说一说一套全面的ws封装:socket.io(在不支持ws的浏览器时,它还有其他方案的实现模拟)
它封装了服务端和客户端一套实现,简化客户端和服务端的编码操作。
首先我们来做一个简易的多客户端向服务端消息交互的demo,从而认识socket.io的用法。
客户端:首先客户端需要引入socket.io
的客户端封装js,从而能够使用到io的api。
所以页面如要引入:
<script src="/socket.io/socket.io.js"></script>
为什么是这样的一个地址呢?这个先带着疑问,看下去。
客户端的socket跟原生ws一样,都是要先建立连接,然后监听消息事件。
通过socket = io.connect('http://localhost:8787');
的方式得到socket对象实例,剩下的操作基本都在socket上调用方法,比如监听消息socket.on('message',function(){})
和发送消息socket.emit('message',{})
详情见如下代码:
到此,客户端部分完成
再来就是服务端:我们需要http模块建立web服务并承载客户端页面,其次则是将socket.io服务绑定到这个web服务
socket.io
源码中有这么一个方法» 在启动socket.io
时,增加了客户端socket.io.js
的一个路由映射,因为前面客户端页面可以通过那样的路径来引入客户端js
这样,一旦启动了服务端的脚本,就架起了web服务和socket.io的服务,就可以在页面上实现向服务端发送消息和向其他客户端发送消息了,就可验证socket.io的使用了,很方便。
最后提一下,websocket支持跨域,那么势必也会有一定的安全方面的考虑,有兴趣可以翻看这篇文章
参考资料:
WebSocket 教程
websocket实战
web 实时通信的方法总结
Web 消息推送及 WebSocket 简介
WebSocket 是什么原理?为什么可以实现持久连接?(知乎)
Web 通信 之 长连接、长轮询(long polling)