Skip to content

WebSocket 是从 HTML5 开始提供的一个在 TCP 协议基础上的全新协议,它基于 HTML5 为浏览器提供了和服务器之间的全双工双向通信通信的能力。

Websocket 初探

在学习 websocket 之前我们还要学习了解一些计算机网络方面的基础知识如:长链接,tcp/ip 协议,http 协议,以及 socket 的基础概念知识。

长连接:长连接是指在一个连接上可以连续的发送多个数据包,在连接期间,如果没有数据包的发送,需要双方发送心跳包,以保持链接的持续性。

tcp/ip:tcp/ip 属于传输层,主要解决数据在网络传输过程中的问题,只管传输数据。

http:http 是属于应用层协议,用于对传输数据的封装解析。从 http1.1 开始默认开启了长连接,也就是我们在请求头中见到的 connection:keep-alive。 这个是长连接告诉客户端保持这个 tcp 通道,可以直接使用这个通道进行通信,而不必新建通道。

socket:socket 又称"套接字",应用程序通过"套接字"发送网络请求或者响应网络请求,它不是协议,它是在程序层面上对传输层协议的接口封装,网络上的两个程序通过一个双向的通信连接实现数据的交换,socket 就是传输通道两端的接口。

websocket 的实现基于 tcp 应用层协议和 socket。

Websocket 的优点

  1. 支持双端通信,服务端可以主动的发送数据给客户端。
  2. 更好的二进制支持,可以发送文本也可以发送二进制。
  3. 数据格式较为轻量,控制开销较小,通信效率高。
  4. 没有同源的限制,可以与任意的服务器进行通信。
  5. 与 http 协议兼容性良好,握手阶段使用的是 http 协议,不容易被屏蔽,能够通过各种 http 代理服务器。
  6. 支持扩展。用户可以扩展协议,或者实现自定义的子协议。

Websocket 的连接建立

websocket 复用了 http 的握手通道,具体表现在,客户端先与服务的端使用 http 协议建立连接,通过 http 请求与服务端协商升级协议,服务端确认协议升级完成后,后续的数据交换便以 websocket 协议的方式进行。

更详细的来说就是:为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息 Upgrade:WebSocket 表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。

浏览器请求

GET ws://console.test.com:2346/ HTTP/1.1
Host: localhost
  Upgrade: websocket
Connection: Upgrade
  Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==
  Origin: http://www.test.com
  Sec-WebSocket-Version: 13

服务器回应

HTTP/1.1 101 Switching Protocols
  Upgrade: websocket
  Connection: Upgrade
  Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=

WebSocket 借用 http 请求进行握手,相比正常的 http 请求,多了一些内容。其中,

Upgrade: websocket
Connection: Upgrade

表示希望将 http 协议升级到 Websocket 协议。 Sec-WebSocket-Key 是浏览器随机生成的 base64 encode 的值,用来询问服务器是否是支持 WebSocket。 服务器返回

Upgrade: websocket
Connection: Upgrade

告诉浏览器即将升级的是 Websocket 协议,Sec-WebSocket-Accept 是将请求包 Sec-WebSocket-Key 的值,与 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 这个字符串进行拼接,然后对拼接后的字符串进行 sha-1 运算,再进行 base64 编码得到的。用来说明自己是 WebSocket 服务器。

Websocket Api 概览

创建 Websocket 对象

var socket = new WebSocket(url,[protocol])

WebSocket 属性

以下是 WebSocket 对象的属性。

属性描述
Socket.readyState只读属性 readyState 表示连接状态,可以是以下值: 0 - 表示连接尚未建立。
1 - 表示连接已建立,可以进行通信。
2 - 表示连接正在进行关闭。
3 - 表示连接已经关闭或者连接不能打开。
Socket.bufferedAmount只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

WebSocket 事件

以下是 WebSocket 对象的相关事件。

事件事件处理程序描述
openSocket.onopen连接建立时触发
messageSocket.onmessage客户端接收服务端数据时触发
errorSocket.onerror通信发生错误时触发
closeSocket.onclose连接关闭时触发

WebSocket 方法

以下是 WebSocket 对象的相关方法。

方法描述
Socket.send()使用连接发送数据
Socket.close()关闭连接

Websocket 的前端示例

javascript
// 打开一个 web socket
var ws = new WebSocket("ws://localhost:9998/echo");

// Web Socket 已连接上,使用 send() 方法发送数据
ws.onopen = function () {
  ws.send("发送数据");
  console.log("数据发送中...");
};

//使用onmessage方法监听服务器发来的消息
ws.onmessage = function (res) {
  var received_msg = res.data;
  console.log("信息接收成功", received_msg);
};

//链接断开使用onclose处理一些其他事情
ws.onclose = function () {
  // 关闭 websocket
  alert("连接已关闭...");
};