###为什么要用WebSocket 虽然HTTP协议简单又简捷,但随着时代的发展,其功能使用上捉襟见肘的疲态已经凸显。但是目前基于HTTP的Web浏览器的使用环境已经遍布全球,完全抛弃HTTP显然不是一个明智之举,基于HTTP,添加新的功能才是王道。
- HTTP的无状态管理,我们通过引入Cookie技术解决。
- HTTP的安全性被人诟病,我们便在TCP上增加一层SSL/TSL
- 为了局部刷新页面,我们通过XMLHttpRequest的API的调用和服务器进行异步通信,达到局部替换加载Web页面。
发现问题,了解问题,解决问题,才是我们应该有的态度。那么针对HTTP协议存在的另一个缺陷,那就是所有的通信只能从客户端发起,而服务器没办法主动推送消息,我们又采用什么办法来解决呢? ####Comet 最先采用的是Comet技术,喜欢看NBA的同学应该都有过这个体验,N年前用功能机看文字直播,信息会自动更新。用的就是这种技术实现的。Comet是一种服务器向页面推送数据的技术,能够让信息近乎实时的推送到页面上。有两种实现Comet的方式:长轮询和HTTP流 #####长轮询 长轮询是短轮询的一个翻版。短轮询是每隔一段时间向服务器发送一次请求,服务器街道请求立即响应,采用XHR对象和setTimeout()就能实现。长轮询则相反,客户端发起请求,服务器接收后便会挂起,直到有了新数据才发送,客户端接受服务器返回的数据做页面局部更新之后便立即再发送一次请求,循环重复上述过程,其实也就是一直递归调用ajax请求。 #####HTTP流 使用轮询,需要一直发送请求。使用流,在页面整个生命周期内,浏览器只向服务器发送一次请求,服务器保持连接一直打开,然后周期性向浏览器发送数据,浏览器利用XHR对象,通过监听readystatechange事件以及检测readystate的值是否为3来决定什么时候获取最新的数据。
不论是轮询还是流(不停发送请求连接或者HTTP连接一直打开),效率都非常低,而且浪费服务器资源。基于此,才有了WebSocket。 ###什么是WebSocket WebSocket通信协议于2011年被定为标准,作为在Web浏览器和Web服务器之间全双工通信标准,主要是为了解决Ajax和Comet里XHR附带的缺陷所引起的问题。
一旦Web服务器与客户端之间建立了WebSocket协议的通信连接,之后所有的通信都依靠这个专用协议进行。通信过程中可以互相发送文本、二进制等任意格式的数据。由于是建立在HTTP基础上的协议,因此连接的发起方仍然是客户端,等建立好WebSocket通信连接,服务器便能直接向客户端发送报文。 ###WebSocket特点
- 推送功能,服务器可以直接向客户端发送数据,而不必等待客户端的请求
- 减少通信量,一旦建立起WebSocket连接,会一直保持连接状态。同HTTP相比,不断减少了每次连接时的开销,而且WebSocket的首部信息很少,通信量也响应的减少了
- 双方可以互相发送任意格式数据,JSON、XML、HTML、图片都可以
- 建立在TCP之上,实现容易
- 跨源通信(虽然仍然应该确保只与自己信任的客户端和服务器通信,但 WebSocket 可实现任何域上多方之间的通信)
###WebSocket连接步骤
- 握手请求,为了实现WebSocket通信,需要客户端在第一次请求时附带HTTP的Upgrade字段,告知服务器通信协议要发生改变
- 握手响应,服务器收到上述请求后,会返回状态码为101 Switching Protocols的响应。
- 握手成功,客户端接收这个101响应,成功握手确立WebSocket链接,在这之后通信便不再使用HTTP协议,而采用WebSocket协议了
###WebSocket使用
// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:8080');
// Connection opened
socket.addEventListener('open', function (event) {
socket.send('Hello Server!');
});
// Listen for messages
socket.addEventListener('message', function (event) {
console.log('Message from server', event.data);
});
WebSocket的使用用例有很多
- 多人在线游戏
- 聊天应用
- 体育赛况直播
- 即时更新社交信息流
自己在express模块的基础上,以node为服务端,基于socket.io实现一个聊天室(socket.io是一个使用WebSocket 标准,提供跨平台实时通信的库,该库对不支持WebSocket的浏览器采取一系列降级功能),github地址