WebSocket 是一个建立在 TCP 之上进行全双工通讯的应用层协议
我们知道,HTTP 协议采用的是请求/响应模式,服务端是不能主动向客户端推送数据的
若要实现推送功能,一般都是采用 Ajax 轮询,但这样频繁的请求会给服务端带来极大的压力
WebSocket 协议就是为了解决这种类似的场景而出现的,它允许服务端可以主动向客户端推送数据
浏览器和服务器通过一次握手,就能在两者之间创建持续性的连接,进行双向数据传输,直至任意一方将其关闭
目前,基于 SHA 加密方式的握手协议是使用最为广泛的,具体的过程如下:
- 浏览器向服务器发起一个 HTTP 请求,但是这个请求与普通的请求不同,它会附加一些头部信息
- 服务器解析头部信息,返回一个响应,这样就能建立起 WebSocket 连接
一个典型的客户端请求如下:
GET ws://localhost:5000 HTTP/1.1 Host: localhost Origin: http://localhost:5000 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: 随机字符串 Sec-WebSocket-Version: 13
Connection
:必须设置为Upgrade
,表示客户端希望升级协议Upgrade
:必须设置为websocket
,表示希望将协议升级为 WebsocketSec-WebSocket-Key
:随机字符串,与响应中Sec-WebSocket-Accept
的值做对比验证
一个典型的服务端响应如下:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: 根据 Sec-WebSocket-Key 计算得到 Sec-WebSocket-Location: ws://localhost:5000
Connection
:如果值为Upgrade
,表示服务端同意升级协议Upgrade
:如果值为websocket
,表示同意将协议升级为 WebsocketSec-WebSocket-Accept
:经过服务器确认并加密的Sec-WebSocket-Key
在理解了原理之后,我们下面再来看一下具体要怎么使用 WebSocket
在客户端浏览器中,可以通过构造函数 WebSocket() 创建一个对象
其中,参数 url 用于指定连接地址,参数 protocol 用于指定可接受的子协议
WebSocket(url, [protocol])
构造函数返回一个 WebSocket 对象,该对象常用的属性和方法如下:
readyState:只读属性,表示连接状态
0 表示连接尚未建立,1 表示连接已经建立,可以进行通信
2 表示连接正在关闭,3 表示连接已经关闭,或者不能打开
bufferedAmount:只读属性,在缓存中等待传输的字节数
onopen:指定 open 事件的监听函数,在连接建立时触发
onmessage:指定 message 事件的监听函数,在收到数据时触发
onerror:指定 error 事件的监听函数,在发生错误时触发
onclose:指定 close 事件的监听函数,在连接关闭时触发
send():发送数据
close():关闭连接
var ws = new WebSocket('ws://localhost:5000') ws.onopen = function(event) { console.log('open') } ws.onmessage = function(event) { console.log('message', event.data) ws.send('Goodbye') ws.close() } ws.onclose = function(event) { console.log('close') }; ws.onerror = function(event) { console.log('error') }
而对于服务器而言,WebSocket 只是一种协议而已,不同的语言和不同的框架会有不同的实现
下面我们以 Node.js 为例,写一个简单的 Demo
var express = require('express') var expressWs = require('express-ws') var app = express() expressWs(app) app.ws('/', function (ws, req){ // ws: WebSocket 实例 // req:Request 实例 ws.send('Hello') ws.on('message', function (msg) { console.log(msg) }) }) var server = app.listen(5000, '127.0.0.1', function() { console.log('server running at http://127.0.0.1:5000') })
文章知识点与官方知识档案匹配,可进一步学习相关知识