admin 管理员组

文章数量: 887021


2023年12月23日发(作者:关于response的短语)

websocket,二进制协议

篇一:WebSocket协议的握手和数据帧

WebSocket协议的握手和数据帧

WebSocket是定义服务器和客户端如何通过Web通信的一种网络协议。协议是通信的议定规则。组成互联网的协议组由IETF(互联网工程任务组)发布。IETF发布评议请求(Request for Comments,RFC),精确地规定了协议(包括RFC 6455):WebSocket协议。RFC 6455于2011年12月发布,包含了实现WebSocket客户端和服务器时必须遵循的规则。 websocket基本上是一个很简单的协议, 主要流程非常少, 实现起来也很简单。 为简单起见, 下面只分析握手和数据帧的报文.

一. 握手(handshake).

握手协议由客户端发起, 服务器响应, 一来一回就完成了.

基本上是为了兼容现有的http基础设施.

下面是一个客户端发起的握手请求: 47 45 54 20 2F 20 48

54 54 50 2F 31 2E 31 0D 0A GET./.HTTP/1.1..55 70 67 72 61

64 65 3A 20 77 65 62 73 6F 63 6B Upgrade:.websock65 74 0D

0A 43 6F 6E 6E 65 63 74 69 6F 6E 3A 20 et..Connection:.55

1

70 67 72 61 64 65 0D 0A 48 6F 73 74 3A 20 31

Upgrade..Host:.139 32 2E 31 36 38 2E 38 2E 31 32 38 3A 31

33 30 92.168.8.128:13030 0D 0A 4F 72 69 67 69 6E 3A 20 6E

75 6C 6C 0D 0..Origin:.null.0A 50 72 61 67 6D 61 3A 20 6E

6F 2D 63 61 63 68 .Pragma:.no-cach65 0D 0A 43 61 63 68 65

2D 43 6F 6E 74 72 6F 6C e..Cache-Control3A 20 6E 6F 2D 63

61 63 68 65 0D 0A 53 65 63 2D :.no-cache..Sec-57 65 62 53 6F

63 6B 65 74 2D 4B 65 79 3A 20 64 WebSocket-Key:.d33 35 39

46 64 6F 36 6F 6D 79 71 66 78 79 59 46

359Fdo6omyqfxyYF37 59 61 63 77 3D 3D 0D 0A 53 65 63 2D

57 65 62 7Yacw==..Sec-Web53 6F 63 6B 65 74 2D 56 65 72 73

69 6F 6E 3A 20 Socket-Version:.31 33 0D 0A 53 65 63 2D 57

65 62 53 6F 63 6B 65 13..Sec-WebSocke74 2D 45 78 74 65 6E

73 69 6F 6E 73 3A 20 78 2D t-Extensions:.x-77 65 62 6B 69

74 2D 64 65 66 6C 61 74 65 2D 66 webkit-deflate-f72 61 6D

65 0D 0A 55 73 65 72 2D 41 67 65 6E 74 rame..User-Agent3A

20 4D 6F 7A 69 6C 6C 61 2F 35 2E 30 20 28

57 :.Mozilla/5.0.(W69 6E 64 6F 77 73 20 4E 54 20 36 2E 31

3B 20 57 .6.1;.W4F 57 36 34 29 20 41 70 70 6C 65

57 65 62 4B 69 OW64).AppleWebKi74 2F 35 33 37 2E 33 36

20 28 4B 48 54 4D 4C 2C t/537.36.(KHTML,20 6C 69 6B 65

20 47 65 63 6B 6F 29 20 43 68 72 .).Chr6F 6D 65

2

2F 33 32 2E 30 2E 31 36 35 33 2E 30 20 ome/32.0.1653.0.53

61 66 61 72 69 2F 35 33 37 2E 33 36 0D 0A 0D

Safari/0A

0D 0A 0D 0A, 也就是用rnrn收尾, 这和http头没什么区别. 转换成字符串就是: GET / HTTP/1.1

Upgrade: websocket

Connection: Upgrade

Host: 192.168.8.128:1300

Origin: null

Pragma: no-cache

Cache-Control: no-cache

Sec-WebSocket-Key: d359Fdo6omyqfxyYF7Yacw==

Sec-WebSocket-Version: 13

Sec-WebSocket-Extensions: x-webkit-deflate-frame

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64)

AppleWebKit/537.36 (KHTML, like Gecko)

Chrome/32.0.1653.0 Safari/537.36

其中有一对重要的kv, 就是Sec-WebSocket-Key:

d359Fdo6omyqfxyYF7Yacw==, 看上去是一个base64编码后的结果, 服务器需要对这个sec-key作一些处理, 并返回握手响应, 这个处理是

:

3

也就是原封不动的拿着这个sec-key和另一个神奇的字符串

258EAFA5-E914-47DA-95CA-C5AB0DC85B11相连, 再经过sha1摘要

算法处理, 最后再经过base64编码输出即可, 上面的输出结果应该是:

pLO2KC7b5t0TZl1E6A3sqJ6EzU4=

服务器在收到握手请求后, 如果愿意提供服务, 则返回一个握手响应, 如下:

遵循http的规则, 字节流上一样是要以rnrn收尾.

二. 数据帧

rfc6455上叫做非控制帧, 除了非控制帧之外, 就是控制帧.

包括connection close, ping, pong等帧, 这里只讲非控制帧,

也就是数据帧.

数据帧从长度上可以分为三种. 帧中的静荷数据(payload

data)长度小于0x7E的为小帧, 静荷数据长度 =0x7E又<=0x10000的为中帧,

再长的叫大帧.

数据帧从类型上暂时可以分为两种, 文本帧和二进制帧.

例子:

a). 一个从客户端发向服务端的小帧.

82

4

二进制为: 1000 0010, 最高位(FIN)为1, 表示这是最后一帧, 第一个帧也可能是最后一帧. 身后还有三位为预留. 低位四0010为操作码.

也就是0x02, 表示这是一个二进制帧, 0x01为文本帧.

B0

二进制为: 1011 0000, 最高位(MASK)为1, 表示当前帧的静荷数据部分使用了掩码, 事实上, rfc6455规定从客户端发往服务器端的数据帧

必需使用掩码, 反过来, 从服务器发回来的, 则必需不使用掩码. 低7位为静荷数据长度字段, 这里是011 0000, 也就是0x30, 从上面的报文上

看, 这个0x30没有包含后面的掩码.

6A F7 C6 30

掩码, 掩码总是四个字节.

0A 一直到最后为经过掩码加工后的静荷数据. 要回到数据本来的面目, 使用下面的算法:

得到的结果应该是:

b). 一个从服务器发给客户端的小帧.

更简单了, 还是82, 最后一帧, 二进制帧, 29, 0010 1001,

无掩码, 也就是身后全长为0x29.

c). 未使用掩码的中帧.

81 7E 01 00 66 77 88 ..., 帧长为 0x0100, 也就是256个字 5

节.

d). 未使用掩码的大帧.

82 7F 00 00 00 00 11 22 33 44 66 77 88 ..., 帧长为0x3344, 直接跳过4字节, 而使用8字节来表示长度, 非常暴力.

这里需要注意的是, websocket要求使用最小帧原则, 也就是静荷数据长度小于0x7E帧, 不能使用中帧或大帧的来表示. 长度小于

0x10000的帧也不能用大帧来表示.

【编辑推荐】

1. 网络协议X档案网络传输协议篇

2. 应用Wireshark观察基本网络协议

3. 移动网络性能揭秘--网络协议及性能提升实践

篇二:一步一步学WebSocket (一) 初识WebSocket

众所周知,Http协议是无状态的,并且是基于Request/Response的方式与服务器进行交互,也就是我们常说的单工模式。但是随着互联网的发展,浏览器与服务端进行双向通信需求的增加,长轮询向服务器以获取最新数据并实现推送效果的方式已经越来越不能满足我们。Html5标准的制定,也为我们提供了浏览器与服务端的双工通信协议WebSocket。WebSocket协议的格式为 ws://IP:Port 或者“wss://IP:Port。其中wss表示进行加密传输的websocket协 6

议。

WebSocket协议与传统的Socket协议一样,都需要进行“握手”。但是WebSocket的“握手”阶段是通过Http协议进行的,“握手”行为通过Request/Response的Header完成,只需要交换很少的数据,便可以创建基于TCP/IP协议的双工通道。下面我们来看一下Fiddler截取到的WebSocket握手请求

通过Fiddler我们可以看到,在握手请求时,客户端向服务端发送了一个Get请求,并且在请求的头中增加了这么几个Key

Origin:IP:Port 表示客户端的地址

Connection:Upgrade / Upgrade:WebSocket 表示本次请求是要进行WebSocket的握手动作

Sec-WebSocket-Version: 13 表示浏览器支持的WebSocket版本信息

Sec-WebSocket-Key: 这是一个由客户端随机生成的字符串

在服务器响应的握手信息中Sec-WebSocket-Accept:的值为服务器通过客户端Header的Sec-WebSocket-Key的值进行计算并加密的结果。

并且服务器的响应状态为101 表示服务器端已经理解了客户端的需求,并且客户端需要根据Upgrade中的协议类 7

型,切换为新的协议来完成后续的通信。

这时候我们的TCP/IP双工通道就已经建立了,WebSocket协议就这么简单。

说完理论知识了,我们来看如何在浏览器中使用WebSocket协议。

最新的FireFox、Chrome、IE10及以上版本都已经支持了WebSocket协议。但是在使用它时,我们需要先检测浏览器是否支持WebSocket协议

WebSocket对象位于 window对象下。我们可以通过以下代码检测浏览器对WebSocket的支持

if(WebSocket in window)

if(ket)

if(MozWebSocket in window)

if(Socket)

如果我们的浏览器支持WebSocket 那么我们就可以创建WebSocket的实例了。

var ws=new WebSocket(ws://localhost:2012);

var ws=new MozWebSocket(ws://localhost:2012);

这里需要注意一下,当我们创建WebSocket的实例时,这个WebSocket实例就已经开始向服务器发起握手请求了,不需要我们手动打开连接。

8

WebSocket对象也很简单,我们会常用到它的4个回调方法 onopen onclose onerror onmessage。他们触发的实际分别为 握手完成并创建TCP/IP通道后,断开连接后,发生错误时,接收到服务端消息时。

另外我们还常常用到一个属性 readyState 用以检查连接状态,和一个函数 send() 向服务端发送数据。

下面我们来完成一个完整的浏览器使用WebSocket的例子,这里需要服务端也支持WebSocket协议

<!DOCTYPE html

<html xmlns=

<meta http-equiv=Content-Type content=text/html;

charset=utf-8 /

篇三:Web应用中的双向通信_Websocket简介

Web 应用中的双向通信 ——WebSockets 简介顾勤 译什么是 WebSockets?WebSockets 规范是在 HTML5 中开始提供的一种浏览器与服务器的 JavaScript 接口,该规范定 义了浏览器与服务器之间进行双全工消息传送的套接字连接。WebSockets 标准大大简化了服务器与 客户端之间的通信与连接管理。关于 HTML5 WebSocketsHTML5

WebSockets 规范定义了一个 API, 允许网页利用

WebSockets 协议与远程主机进行双向 通信。 该规范介绍了 WebSockets 接口, 并定义了一个通过网络上单一的套 9

接字连接的双全工通信频 道。相对于两种模拟双全工连接的解决方案:轮询和长轮询,HTML5 WebSockets 降低了大量不必 要的网络传输和延迟。 HTML5 WebSockets 能够穿过网络上的一些障碍,如代理和防火墙,让数据流能够使用任意连 接传输,并在单一连接中支持上行数据流和下行数据流,基于 HTML5 WebSockets 的应用能减少服 务器的负担, 使现有的机器能够支持更多的并发连接数。 下图说明了一个基本的 WebSocket 的架构, 该架构中浏览器利用 WebSocket 与服务器进行双全工、直接的通信。WebSocket 的一个独特的功能就是穿越防火墙和代理的能力,很多应用程序都面临着这样的问 题。Comet 风格的应用程序采用长轮询作为解决防火墙和代理问题的基本方法。该技术虽有效,但 不适用于低于 500 毫秒的延迟或高吞吐量要求的应用程序。基于插件的技术,如 Adobe Flash,也提 供 一 定 的套 接 字接 口 支持 , 但 长期 以 来 也

一 直存 在 难 以穿 过 代理 和 防火 墙 的 问题 , 而现 在 WebSockets 解决了这个问题。 WebSocket 会检测存在的代理服务器,并自动设置穿越代理的通道。这个通道是通过发起一个 与代理服务的 HTTP CONNECT 声明来建立的,这需要代理服务器在指定的主机和端口上打开一个

TCP/IP 连接。一旦通道创建完成,就可以顺利穿过代理进行通信。由于 HTTP 和 HTTPS 的工作原

10

理相似,因此通过 SSL 的安全 WebSockets 可以采用与

HTTP CONNECT 相同的方法。要注意的是, 现在的浏览器都是最近才开始支持 WebSockets Chrome 浏览器最初版本就支持 WebSockets) 然而, ( 。 今天的浏览器都实现了向后兼容性,因而能够充分利用这一新兴技术。

WebSocket 和其它 HTML5 支持的特性(如本地存储和地理定位)一样,都是原始 HTML5 规范 的一部分,但为了更加重视,WebSocket 被分离成为一个独立的标准。WebSocket 被它的作者—— 网页超文本技术工作小组(WHATWG)提交给了 Internet 工程任务组(IETF) 。参与标准制定的作 者、传播者和公司,仍将 WebSockets 视为 HTML5 原始功能部件的集合中的一部分。 WebSocket

协议 WebSocket 协议的设计,使它在现有网络设施的基础上也能够很好的工作。基于这一设计原则, 协议规定:WebSocket 的生命周期从一个 HTTP 连接开始,以保证完全兼容 WebSocket 诞生之前的 网络环境。从 HTTP 到

WebSocket 协议的转换被称为 WebSocket 握手。 浏览器向服务发送一个请求,表明它要将协议由 HTTP 转为

WebSocket。客户端通过 HTTP 头中的 Upgrade 属性来表达这一请求:GET ws:///?encoding=text

HTTP/1.1

__utma=99as

Origin:

Upgrade

Cookie:

Host: Connection:

11

uRovscZjNol/umbTt5uKmw==

Sec-WebSocket-Key:

Upgrade: websocket

Sec-WebSocket-Version: 13如果服务器支持 WebSocket 协议,同样通过 HTTP 头中的 Upgrade 属性来表示同意进行协议的转 换:HTTP/1.1 101 WebSocket Protocol

Handshake Date: Fri, 10 Feb 2012 17:38:18 GMT

Connection: Upgrade Server: Kaazing Gateway Upgrade:

WebSocket Access-Control-Allow-Origin:

Access-Control-Allow-Credentials: true

Sec-WebSocket-Accept:

rLHCkw/SKsO9GAH/ZSFhBATDKrU=

Access-Control-Allow-Headers: content-type此时,HTTP 协议被取消,取而代之的是一个基于 TCP/IP 的 WebSocket

连接。WebSocket 连接默 认使用与 HTTP(80)或 HTTPS(443)相同的端口。

一旦建立起连接,客户端与服务器之间可以用双全工模式传输 WebSocket 数据帧。文本或二进制 帧可以在任意方向上同时进行传输。最小的数据帧仅为 2 字节。如果是文本帧,每帧以 0x00 开始, 以 0xFF 结束,中间为 UTF-8 格式的数据。WebSocket 文本使用终结符,而二进制帧使用长度作为帧 的前缀。使用 HTML5 WebSocket API通过一个简洁的接口说明(参见下面的列表) ,开发人员可以替代 12

如长轮询或持久框架,从而进 一步降低延迟。[Constructor(in DOMString url, optional in DOMString

protocol)] interface WebSocket { readonly attribute

DOMString URL; // ready state const unsigned short

CONNECTING = 0; const unsigned short OPEN = 1; const

unsigned short CLOSED = 2; readonly attribute unsigned

short readyState; readonly attribute uns(来自: 小龙文 档网:websocket,二进制协议)igned long bufferedAmount; // networking attribute

Function onopen; attribute Function onmessage; attribute

Function onclose; boolean send(in DOMString data); void

close(); }; WebSocket implements EventTarget;使用

WebSocket 接口非常简单,要连接到一个终端,只需要创建一个新的 WebSocket 实例,参照 以下的示例,为这个新的对象提供一个表示你想要连接终端的 URL。请注意,ws://和 wss://前缀分 别表示普通 WebSocket 和安全

WebSocket 连接。var myWebSocket = new

WebSocket(ws://);在客户端与服务器初次握手时,将 HTTP 协议升级成 WebSocket 协议,从而创建了一个新的 WebSocket 连接。通过 WebSocket 接口中定义的“onmessage”和“send”函数,将这个连接暴露出

来。 参照下面的例子,在连接一个终端并发送消息之前, 13

你可以结合一系列的事件监听器来处理这个 连接生命周期的每一个阶段。 = function(evt)

{ alert(Connection open ...); }; age =

function(evt) { alert( Received Message: + ); };

e = function(evt) { alert(Connection

closed.); };要将消息发送到服务器,你只需要简单的调用“send”方法,并提供需要发送的消息内容。信息 传送完成后,调用“close”方法来终止这个连接,就像下面给出的这个例子一样。正如你看到的, 已经简单的不能再简单了。(Hello

();原WebSockets!);

文:/

14


本文标签: 协议 连接 握手 数据