WebSocket协议学习笔记

协议产生背景

  图1展示了WebSocket协议产生的背景。

websocket协议产生背景

图1 WebSocket协议产生的背景

建立WebSocket通信

客户端

  HTML5将WebSocket协议标准化,目前各大主流浏览器均已支持WebSocket协议。浏览器提供了一个WebSocket对象用来创建和管理WebSocket连接。客户端可以利用这一对象与服务器进行WebSocket通信。一个简单的客户端建立WebSocket通信的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:3000');
// Connection opened
socket.addEventListener('open', () => {
alert('websocket协议握手成功!!!');
});
// Listen for messages
socket.addEventListener('message', (event) => {
alert('收到新消息!!!');
});
// Connection closed
socket.addEventListener('close', () => {
alert('停止websocket协议!!!');
});

服务端

  目前,针对不同的服务器环境均有对应的WebSocket框架可以使用,详情可见维基百科。适用于Node环境的WebSocket框架主要有以下几类:

  以Node环境下的ws框架为例,一个简单的服务器端实现WebSocket协议的示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// import http module
const http = require('http');
// import ws
const websocket = require('ws');
// create http server
const server = http.createServer(app.callback());
// create websocket instance
const websocketServer = new websocket.Server({server});
// listen for connection
websocketServer.on('connection', (ws, req) => {
// listen for messages
ws.on('message', (msg) => {
console.log("收到了新消息!!!");
ws.send('您好,我已经收到了你的消息');
});
});

WebSocket协议握手

  WebSocket协议使用了http协议的握手通道,由http协议升级到WebSocket协议时的http报文示例如下:

  • request
    websocket协议握手时http请求报文

  • response
    websocket协议握手时http响应报文

  上述http报文中与WebSocket协议握手阶段相关的字段解释如下:

表1 WebSocket协议握手阶段http报文首部相关字段解释
字段名称 含义
Connection: Upgrade 表示要升级协议。
Upgrade:websocket 表示要升级到WebSocket协议。
Sec-WebSocket-Extensions 仅用在WebSocket连接握手阶段。它先由客户端(浏览器)发送到服务器,然后再由服务器传回客户端,以便协商连接过程中的协议层扩展集。可能在HTTP请求中出现多次(等价于出现一次,但有多个值),但是最多只能在HTTP响应中出现一次。
Sec-WebSocket-Key Base64编码字符串,与服务端响应首部的Sec-WebSocket-Accept是配套的,提供基本的防护,比如恶意的连接,或者无意的连接。
Sec-WebSocket-Version 表示websocket的版本。如果服务端不支持该版本,需要返回一个Sec-WebSocket-Version首部字段,里面包含服务端支持的版本号。
Sec-WebSocket-Accept Base64编码字符串,根据客户端请求首部的Sec-WebSocket-Key计算出来。

  Sec-WebSocket-Accept字段计算公式:

  1. Sec-WebSocket-Key258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接。
  2. 通过SHA1计算出摘要,并转成base64字符串。伪代码:toBase64(sha1(Sec-WebSocket-Key + 258EAFA5-E914-47DA-95CA-C5AB0DC85B11))

参考文献

  1. http://www.ruanyifeng.com/blog/2017/05/websocket.html
  2. https://www.zhihu.com/question/20215561
  3. https://mp.weixin.qq.com/s/rKvoevbSmtAUoCgOH2lZdQ
  4. http://blog.csdn.net/tennysonsky/article/details/44562435
  5. https://blog.lyz810.com/article/2016/06/websocket-handshake-server-response/