物联网相关技术研究

WebSocket

2018-03-31  本文已影响7人  freelamb

基本知识

WebSocket 是一种应用层协议,基于TCP协议;
WebSocket protocol 是HTML5一种新的协议。它是实现了浏览器与服务器全双工通信(full-duplex)。

WebSocket通信过程

WebSocket通信过程

客户端发起握手请求

客户端发送握手请求内容

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: [http://example.com](http://example.com/)
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

字段说明

客户端发送握手请求的要求

服务端回应握手请求

握手服务端返回内容

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

字段说明

在请求中的“Sec-WebSocket-Key”是随机的,服务器端会用这些数据来构造出一个SHA-1的信息摘要。把“Sec-WebSocket-Key”加上一个魔幻字符串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”。使用SHA-1加密,之后进行BASE-64编码,将结果做为“Sec-WebSocket-Accept”头的值,返回给客户端。

服务器端响应步骤

WebSocket关闭握手

当WebSocket关闭时,终止连接的端点可以发送一个数字代码,以及一个表示选择关闭套接字原因的字符串。代码和原因编码为具有关闭操作码(8)的一个帧的载荷。数字代码用一个16位无符号整数表示,原因则是一个UTF-8编码的短字符串。RFC 6455定义了多种特殊的关闭代码。代码1000~1015规定用于WebSocket连接层。这些代码表示网络中或者协议中的某些故障。

WebSocket关闭代码的定义

代码 描述 何时使用
1000 正常关闭 当你的会话成功完成时发送这个代码
1001 离开 因应用程序离开且不期望后续的连接尝试而关闭连接时,发送这一代码。服务器可能关闭,或者客户端应用程序可能关闭
1002 协议错误 当因协议错误而关闭连接时发送这一代码
1003 不可接受的数据类型 当应用程序接收到一条无法处理的意外类型消息时发送这一代码
1004 保留 不要发送这一代码。根据RFC 6455,这个状态码保留,可能在未来定义
1005 保留 不要发送这一代码。WebSocket API用这个代码表示没有接收到任何代码
1006 保留 不要发送这一代码。WebSocket API用这个代码表示连接异常关闭
1007 无效数据 在接收一个格式与消息类型不匹配的消息之后发送这一代码。如果文本消息包含错误格式的UTF-8数据,连接应该用这个代码关闭
1008 消息违反政策 党应用程序由于其他代码所包含的原因终止连接,或者不希望泄露消息无法处理的原因时,发送这一代码
1009 消息过大 当接受的消息太大,应用程序无法处理时,发送这一代码(记住,帧的载荷长度最多为64字节。即使你有一个大服务器,有些消息也仍然太大)
1010 需要扩展 当应用程序需要一个或者多个服务器无法协商特殊扩展时,从客户端发送这一代码
1011 意外情况 当应用程序由于不可预见的原因,无法继续处理连接时,发送这一代码
1015 TLS失败(保留) 不要发送这个代码。WebSocket API用这个代码表示TLS在WebSocket握手之前失败

WebSocket URI

定义的两个协议框架ws和wss与http类似,而且各自部分的要求也是在HTTP协议中使用的一样,各自的URI如下:

ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]
其中port是可选项,query前接“?”

WebSocket API

// 创建一个Socket实例
var socket = new WebSocket('ws://localhost:8080', [protocal]); 
// 连接建立,即握手成功触发的事件;
socket.onopen = function(event) { 
// 发送一个初始化消息
socket.send('I am the client and I\'m listening!'); 
// 收到服务器消息时触发的事件
socket.onmessage = function(event) { 
console.log('Client received a message',event); 
}; 
// 异常触发的事件
socket.onerror=function(event){
console.log(,"error: " event);
}
// 关闭连接触发的事件
socket.onclose = function(event) { 
console.log('Client notified socket has closed',event); 
}; 
// 关闭连接
socket.close();

Socket.readyState只读属性readyState表示连接的状态。有以下取值:

CONNECTING(0) 表示连接尚未建立;
OPEN(1) 表示连接已建立,可以进行通信;
CLOSING(2) 表示连接正在进行关闭握手;
CLOSED(3) 表示连接已经关闭或者连接不能打开。

WebSocket包结构

WebSocket包结构

FIN: 最高位用于描述消息是否结束,如果为1则该消息为消息尾部,如果为零则还有后续数据包;
RSV: 后面3位是用于扩展定义的,如果没有扩展约定的情况则必须为0。
OPCODE: 最低4位用于描述消息类型,消息类型暂定有15种,其中有几种是预留设置,操作码定义如下:

操作码 消息载荷类型 描述
0 连续消息标识 表示连续消息片段
1 文本 消息的数据类型为文本
2 二进制 消息的数据类型为二进制
3~7 保留 为将来的非控制消息片断保留操作码
8 关闭 客户端或者服务器向对方发送关闭握手
9 ping 客户端或者服务器向对方发送ping
A pong 客户端或者服务器向对方发送pong
B~F 保留 为将来的控制消息片断的保留操作码

Mask:最高位用0或1来描述是否有掩码处理,也就是所说的屏蔽。从浏览器向服务器发送的WebSocket帧内容进行了“屏蔽”,以混淆其内容。屏蔽的目的不是阻止窃听,而是为了不常见的安全原因,以及改进和现有HTTP代理的兼容性。
Payload length: 传输数据的长度,以字节的形式表示:7位、7+16位、或者7+64位。如果这个值以字节表示是0-125这个范围,那这个值就表示传 输数据的长度;如果这个值是126,则随后的两个字节表示的是一个16进制无符号数,用来表示传输数据的长度;如果这个值是127,则随后的是8个字节表示的一个64位无符号数,这个数用来表示传输数据的长度。多字节长度的数量是以网络字节的顺序表示。负载数据的长度为扩展数据及应用数据之和,扩展数据的长度可能为0,因而此时负载数据的长度就为应用数据的长度。
Masking-key:0或4个字节,客户端发送给服务端的数据,都是通过内嵌的一个32位值作为掩码的;掩码键只有在掩码位设置为1的时候存在。
Payload data: (x+y)位,负载数据为扩展数据及应用数据长度之和。
Extension data:x位,如果客户端与服务端之间没有特殊约定,那么扩展数据的长度始终为0,任何的扩展都必须指定扩展数据的长度,或者长度的计算方式,以及在握手时如何确定正确的握手方式。如果存在扩展数据,则扩展数据就会包括在负载数据的长度之内。
Application data:y位,任意的应用数据,放在扩展数据之后,应用数据的长度=负载数据的长度-扩展数据的长度。

WSS

wss是安全的WebSocket通信协议

注意问题

  1. 握手过程中,HTTP request method 必须是GET,协议应不小于1.1
  2. 所有数据传输都是UTF-8编码的数据,当一端接收到的字节流数据不是一个有效的UTF-8数据流,那个么接收到的这一方必须要马上关闭连接。这个规则在开始握手一直到所有的数据交换过程都要进行验证。

浏览器支持

下面是主流浏览器对 HTML5 WebSocket 的支持情况:
http://caniuse.com/#search=websocket

浏览器 支持情况
Chrome Supported in version 4+
Firefox Supported in version 4+
Internet Explorer Supported in version 10+
Opera Supported in version 10+
Safari Supported in version 5+

参考

WebSocket 教程

上一篇下一篇

猜你喜欢

热点阅读