一、概念
WebSocket 是 HTML5 新增的 API,是一种基于 TCP 连接的持久化双向通信协议。
WebSocket 使用 HTTP 来连接,连接后就切换到(Upgrade)WebSocket 协议了,所以连接还是基于 HTTP 协议,但是数据通信是通过 TCP 通道传输,无 HTTP 无关 。
WebSocket 默认连接端口是80,运行端口是443。
WebSocket 连接地址示例(以 ws 或者 wss 开头):ws://text.com:8888 或 wss://text.com:8888(加密)。
二、特点
1. 实时性:实现双向通信,服务端也可以主动推送消息;
2. 持久性:WebSocket 通过 HTTP/1.1 的101状态码进行握手,客户端与服务端只需要建立一次连接,便建立了永久连接,可以一直通信,除非有一端主动断开连接;
3. 较少的数据包头部:在不包含拓展的情况下,服务端到客户端的头部只有2-10字节,客户端到服务器加上4字节的掩码,而 HTTP 请求每次都要携带完整的头部信息;
4. 可拓展性:用户可以扩展协议、实现部分自定义的子协议。如部分浏览器支持压缩等 。
三、应用
1. 在浏览器使用 WebSocket 协议步骤。
1) 创建 WebSocket 实例对象
var Socket = new WebSocket(url, [protocol] );
//url:为制定连接的 URL;
//protocol:可选,自定义子协议。
2) 建立连接并发送报文
socket.onopen = function(){
socket.send("发送数据");
};
3) 监听服务端返回数据
socket.onmessage = function (evt){
var msg = evt.data;
};
4) 关闭连接
socket.onclose = function(){};
完整的示例如下
function WebSocket(){
//判断是否支持 websoket 协议
if ("WebSocket" in window){
//1.创建 socket 对象
var socket = new WebSocket("ws://localhost:9998/echo");
//2.建立连接
socket.onopen = function(){
//3.发送报文
socket.send("发送数据");
};
//4.监听服务端返回的消息
socket.onmessage = function (evt){
var msg = evt.data;
};
//5.关闭连接
socket.onclose = function(){};
} else {
// 浏览器不支持 WebSocket
alert("您的浏览器不支持 WebSocket!");
}
2. Socket 对象属性、事件及方法
- 属性(6个)
readyState:只读属性,表示连接状态 ,有0(连接未建立),1(已建立,可通信),2(正在关闭),3(已关闭或不能打开)四个值。
bufferedAmount:只读属性,已被 Socket.send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。
extensions:只读属性,返回服务器已选择的扩展值。目前,链接可以协定的扩展值只有空字符串或者一个扩展列表。
protocol:只读属性,服务器选择的下属协议。
url:只读属性,绝对路径。
binarytype:使用二进制的数据类型连接。
- 事件(4个)
onopen 连接建立时触发,
onmessage 客户端接收服务端消息时触发,
onerror 通信发生错误时触发,
onclose 连接关闭时触发,
- 方法(2个)
send() 发送数据
close() 关闭连接
3. WebSocket 协议报文头
- 请求头
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
- 响应头
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
- 参数说明
Connection:Upgrade 表示要升级协议
Upgrade:表示要升级为 websoket 协议
Sec-WebSocket-Key:是一个base64 encode值,由浏览器随机生成,与服务端 Sec-WebSocket-Accept 呼应,提供基本的防护,比如恶意连接或无意挂起,也确保服务端知道这是个 Websoket 协议而不是 HTTP 协议 。
Sec-WebSocket-Protocol:用户自定义字符串,用来区分不同的服务所需要的协议。
Sec-WebSocket-Version:表示 websocket 的协议版本,如果服务端不支持该版本,需要返回 Sec-WebSocket-Version 这个头说明支持的版本。
Sec-WebSocket-Accept:经过服务器确认,并且加密的 Sec-WebSocket-Key,客户端会根据这个字段在本地做一次验证,如果验证通过了,就会触发 onopen 函数。
四、意义
假设要实现一个秒杀活动,秒杀价格可能实时变化,就需要服务端主动推送数据给客户端,实现这种需求目前最常见的方式有两种。
- Ajax 轮询,即每隔一段时间就向后台发送一次 HTTP 请求,在请求中,可能会有较长的请求头,但是所需要的数据可能只是很小的一部分,所以很浪费带宽和时间。
- Comet(基于 HTTP 长连接,无需在浏览器端安装插件的“服务器推”技术),这种也能实现双向通信,但每次也需要客户端主动去发送请求,而且普通采用长连接,非常消耗资源。
如果使用 WebSocket 协议,不用客户端每次发请求,服务端可以主动推动数据,就能有效地利用资源和实现实时通信。