websocket,二进制协议
篇一:WebSocket协议的握手和数据帧
WebSocket协议的握手和数据帧
WebSocket是定义服务器和客户端如何通过Web通信的一种网络协议。协议是通信的议定规则。组成互联网的协议组由IETF(互联网工程任务组)发布。IETF发布评议请求(Request for Comments,RFC),精确地规定了协议(包括RFC 6455):WebSocket协议。RFC 6455于2011年12月发布,包含了实现WebSocket客户端和服务器时必须遵循的规则。websocket基本上是一个很简单的协议, 主要流程非常少, 实现起来也很简单。为简单起见, 下面只分析握手和数据帧的报文.
一. 握手(handshake).
socket通信报文格式握手协议由客户端发起, 服务器响应, 一来一回就完成了. 基本上是为了兼容现有的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
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 indows.NT.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 .like.Gecko).Chr6F 6D 65
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, 也就是用\r\n\r\n收尾, 这和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作一些处理, 并返回握手响应, 这个处理是
:
也就是原封不动的拿着这个sec-key和另一个神奇的字符串
258EAFA5-E914-47DA-95CA-C5AB0DC85B11相连, 再经过sha1摘要
算法处理, 最后再经过base64编码输出即可, 上面的输出结果应该是:
pLO2KC7b5t0TZl1E6A3sqJ6EzU4=
服务器在收到握手请求后, 如果愿意提供服务, 则返回一个握手响应, 如下:
遵循http的规则, 字节流上一样是要以\r\n\r\n收尾.
二. 数据帧
rfc6455上叫做非控制帧, 除了非控制帧之外, 就是控制帧. 包括connection close, ping, pong等帧, 这里只讲非控制帧, 也就是数据帧.
数据帧从长度上可以分为三种. 帧中的静荷数据(payload data)长度小于0x7E的为小帧, 静荷数据长度=0x7E又<=0x10000的为中帧,
再长的叫大帧.
数据帧从类型上暂时可以分为两种, 文本帧和二进制帧.
例子:
a). 一个从客户端发向服务端的小帧.
82
二进制为: 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个字
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论