Description
什么是 WebSocket
WebSocket 是一个双向、全双工的即时通信协议,它与 HTTP 协议一样基于 TCP,在客户端和服务器之间建立连接。WebSocket 是有状态的,这意味着一旦建立连接,就能一直保持连接打开,类似 Keep Alive
的能力,直到其中一方主动关闭断开连接。
那为什么需要 WebSocket 呢?这就要从 HTTP 说起,很早以前网络传输都是使用的 http,这是典型的 客户端-服务器
模式。客户端发起一个 http 请求,服务器响应资源,随后连接被关闭。这是一个单向的过程,而且控制权在 客户端
这边。通常是由客户端去发起请求,然后服务端作应答。那有没办法让服务端也可以向客户端发送消息呢?实际上 HTTP2 已经支持 Server Push
的功能,但这只是服务端去主动发送附带资源给客户端,客户端并没有一个明确的事件可以监听到服务端发来的数据。所以想实现真正的双向通信,还需要有专门的机制才行。于是 HTML5 新增了 WebSocket 协议,它支持双向、全双工通信,客户端和服务端都可以收发消息,而且是实时通信,端到端接收。
如何建立 WebSocket 连接
客户端和服务器需要进行 握手
,通常是客户端先发送一个 http 请求,在请求头有个 Upgrade
字段, 表示希望升级成 WebSocket 连接。请求示例如下:
GET ws://websocket.example.com/ HTTP/1.1
Origin: http://example.com
Connection: Upgrade
Host: websocket.example.com
Upgrade: websocket
服务端如果同意,就会响应 101
状态码,告诉客户端说可以切换使用 WebSocket 协议,响应 payload 示例如下:
HTTP/1.1 101 Switching Protocols
Date: Wed, 25 Oct 2017 10:07:34 GMT
Connection: Upgrade
Upgrade: WebSocket
当连接建立的时候,就会触发 open
事件,可以通过监听该事件来执行操作:
var socket = new WebSocket('ws://websocket.example.com');
socket.onopen = function(event) {
console.log('WebSocket is connected.')
}
这时 socket 连接已经建立完毕,接下来客户端和服务端都可以发送消息了,可以通过 send
方法来发送消息,通过监听 message
事件来接收消息。对于错误处理,可以监听 error
事件来处理。对于关闭连接,通过监听 close
事件。
socket.onmessage = function(event) {
console.log('接收的数据:', event.data)
}
socket.onclose = function(reasonCode, description) {
console.log('close: ', reasonCode, description)
}
socket.onerror = function() {
console.log('error')
}
WebSocket 的心跳机制
心跳机制
是指连接建立后,客户端和服务端两方都可以通过发送 ping
报文,然后另一方接收到后,必须回复一个 pong
报文。这样做的目的是为了探测其中一方是否还处于连接状态。由于 WebSocket 是双向传输,任意一方都可以发送消息及断开连接,如果出现一些意外情况比如网络错误导致其中一方断开了,那如何让另一方发现呢?这就要有一个探测机制,来实时检查对方的连接状态,避免无谓等待所带来的花销。所以心跳机制就是让双方都确认对方的在线状态。
WebSocket 的应用场景
- 实时网络通信应用程序,比如 QQ 聊天,对话框里互相发送消息,群发消息就是使用的 WebSocket
- 游戏 APP:平时我们玩的游戏,对实时性要求非常高,因为数据不断地被服务器接受处理,但是我们看屏幕 UI 是自动刷新的,这就使用了 WebSocket 技术
WebSocket 与 HTTP 的区别
- HTTP 是单向通信,比如客户端发送,服务端响应;而 WebSocket 是双向通信,实时收发消息
- HTTP 是
无状态的
,协议以http(s)://
开头,而 WebSocket 是有状态的,以ws(s)://
开头 - WebSocket 是长连接的,除非一方主动关闭否则一直保持连接;而 HTTP 连接数据传输完就会被关闭
- WebSocket 传输数据比 HTTP 连接快
即时通信的其它解决方案
除了 WebSocket 外,以下技术也可以实现即时通信:
短轮询
:前端每隔一段时间发起 ajax 请求,获取服务器更新内容长轮询
:是对短轮询
的改进,客户端发起请求到服务器后,一直保持打开状态,等服务器有内容更新就响应一次数据。SSE
:Server Sent Event,基于流的服务端推送技术。它允许服务端异步的向客户端推送数据,它有点类似发布-订阅
模式,服务端可以决定向客户端发送哪些数据,客户端可以通过一套 API 来订阅内容的获取。Socket.IO
: 基于WebSocket
做了一些兼容性工作,封装了一些更好用的接口。