WebSocket握手协议

1、客户端握手请求(注意:键值之间有一个空格,行间有换行符号0x13x10或者说\r\n)
GET /WebSocket/LiveVideo HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: localhost:8080             (客户端请求主机)
Origin: http://127.0.0.1         (来源网页地址)
Sec-WebSocket-Key1: 23 asdfJKj,asdjk
Sec_WebSocket-Key2: wewerw234 jij998
0x13x10 + 8个字节Sec_WebSocket-Key3值,没有键名(注意,这里的0x13x10的额外的,也就说有两个连续的0x13x10)

2、服务端握手回复
HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Origin: http://127.0.0.1     (来源网页地址)
Sec-WebSocket-Location: ws://localhost:8080/WebSocket/LiveVideo
16个字节的加密KEY

加密KEY算法:

Sec_WebSocket-Key1的产生方式:
(1)提取客户端请求的Sec_WebSocket-Key1中的数字符组成字符串k1
(2)转换字符串为8个字节的长整型intKey1
(3)统计客户端请求的Sec_WebSocket-Key1中的空格数k1Spaces
(4)intK1/k1Spaces取整k1FinalNum
(5)将k1FinalNum转换成字节数组再反转最终形成4个字节的Sec_WebSocket-Key1

Sec_WebSocket-Key2的产生方式:
(1)提取客户端请求的Sec_WebSocket-Key2中的数字符组成字符串k2
(2)转换字符串为8个字节的长整型intKey2
(3)统计客户端请求的Sec_WebSocket-Key2中的空格数k2Spaces
(4)intK2/k2Spaces取整k2FinalNum
(5)将k2FinalNum转换成字节数组再反转最终形成4个字节的Sec_WebSocket-Key2

Sec_WebSocket-Key3的产生方式:
客户端握手请求的最后8个字节

将Sec_WebSocket-Key1、Sec_WebSocket-Key2、Sec_WebSocket-Key3合并成一个16字节数组
再进行MD5加密形成最终的16个字节的加密KEY

3、消息发送接收
客户端和服务端发送非握手文本消息时,消息以utf-8编码,并以0x00开头,0xFF结尾。

WebScoket 规范
4.1 握手协议
websocket 是 独立的基于TCP的协议, 其跟http协议的关系仅仅是 WebSocket 的握手被http 服务器当做 Upgrade request http包处理。 websocket 有自己的握手处理。 TCP连接建立后,client 发送websocket 握手请求. 请求包需求如下:
必须是有效的http request 格式
HTTP request method 必须是GET,协议应不小于1.1 如: Get /chat HTTP/1.1
必须包括Upgrade 头域,并且其值为“websocket”
必须包括"Connection" 头域,并且其值为 "Upgrade"
必须包括"Sec-WebSocket-Key"头域,其值采用base64编码的随机16字节长的字符序列, 服务器端根据该域来判断client 确实是websocket请求而不是冒充的,如http。响应方式是,首先要获取到请求头中的Sec-WebSocket-Key的值,再把这一段 GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"加到获取到的Sec-WebSocket-Key的值的后面,然后拿这个 字符串做SHA-1 hash计算,然后再把得到的结果通过base64加密,就得到了返回给客户端的Sec-WebSocket-Accept的http响应头的值。
如果请求来自浏览器客户端,还必须包括Origin头域 。 该头域用于防止未授权的跨域脚本攻击,服务器可以从Origin决定是否接受该WebSocket连接。
必须包括"Sec-webSocket-Version" 头域,当前值必须是13.
可能包括"Sec-WebSocket-Protocol",表示client(应用程序)支持的协议列表,server选择一个或者没有可接受的协议响应之。
可能包括"Sec-WebSocket-Extensions", 协议扩展, 某类协议可能支持多个扩展,通过它可以实现协议增强
可能包括任意其他域,如cookie
示例如下:
        GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Server 接手到握手请求后应处理该请求包括:
处理请求包括处理GET 方法
验证Upgrader头域
验证Connection 头域
处理Sec-WebSocket-Key头域,方法见上;
处理Sec-WebSocket-Version
处理Origin头域,可选, 浏览器必须发送该头域
处理Sec-WebSocket-Protocol头域,可选
处理Sec-WebSocket-Extensions 头域,可选
处理其他头域,可选
Server 发送握手响应,这里只介绍服务器接受该连接情况下,包括:
http Status-Line
Upgrade 头域 ,值必须是"websocket"
Conntion头域,值必须是:“Upgrade”
Sec-WebSocket-Accept” 头域,该头域的值即处理Sec-WebSocket-Key" 域后的结果。
可选的"Sec-WebSocket-Protocol"头域
可选的"Sec-WebSocket-Extensions"头域
响应可能如下:
        HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
4.2 数据传输
   在WebSocket 协议中,使用序列frames方式来传输数据。一个frame的标准格式如下:
      0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len |    Extended payload length    |
|I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
|N|V|V|V|       |S|             |   (if payload len==126/127)   |
| |1|2|3|       |K|             |                               |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|     Extended payload length continued, if payload len == 127  |
+ - - - - - - - - - - - - - - - +-------------------------------+
|                               |Masking-key, if MASK set to 1  |
+-------------------------------+-------------------------------+
| Masking-key (continued)       |          Payload Data         |
+-------------------------------- - - - - - - - - - - - - - - - +
:                     Payload Data continued ...                :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                     Payload Data continued ...                |
+---------------------------------------------------------------+
FIN:1位,是否是消息的结束帧(分片)
RSV1, RSV2, RSV3: 分别都是1位, 预留,用于约定自定义协议。 如果双方之间没有约定自定义协议,那么这几位的值都必须为0,否则必须断掉WebSocket连接;
Opcode:4位操作码,定义有效负载数据,如果收到了一个未知的操作码,连接也必须断掉,以下是定义的操作码:
%x0 表示连续消息分片
%x1 表示文本消息分片
%x2 表未二进制消息分片
%x3-7 为将来的非控制消息片断保留的操作码
%x8 表示连接关闭  %x9 表示心跳检查的ping
%xA 表示心跳检查的pong
%xB-F 为将来的控制消息片断的保留操作码
Mask: 定义传输的数据是否有加掩码,如果设置为1,掩码键必须放在masking-key区域,客户端发送给服务端的所有消息,此位的值都是1;
Payload length: 传输数据的长度,以字节的形式表示:7位、7+16位、或者7+64位。如果这个值以字节表示是0-125这个范围,那这个值就表示传输数据的长度;如果 这个值是126,则随后的两个字节表示的是一个16进制无符号数,用来表示传输数据的长度;如果这个值是127,则随后的是8个字节表示的一个64位无符 合数,这个数用来表示传输数据的长度。多字节长度的数量是以网络字节的顺序表示。负载数据的长度为扩展数据及应用数据之和,扩展数据的长度可能为0,因而 此时负载数据的长度就为应用数据的长度。注意Payload length不包括Masking-key在内。
Masking-key: 0或4个字节,客户端发送给服务端的数据,都是通过内嵌的一个32位值作为掩码的;掩码键只有在掩码位设置为1的时候存在。 数据Mask方法是,第 i byte 数据 = orig-data ^ (i % 4) .
Payload data: (x+y)位,负载数据为扩展数据及应用数据长度之和。
Extension data:x位,如果客户端与服务端之间没有特殊约定,那么扩展数据的长度始终为0,任何的扩展都必须指定扩展数据的长度,或者长度的计算方式,以及在握手时如何确定正确的握手方式。如果存在扩展数据,则扩展数据就会包括在负载数据的长度之内。
Application data:y位,任意的应用数据,放在扩展数据之后,应用数据的长度=负载数据的长度-扩展数据的长度。
把消息分片处理主要是处于以下两个原因:
消息接收方事先并不知道消息大小, 而且也没必要预留一个足够大的buffer来处理;
multiplexing
消息分片一些规则如下(不全):
为分片消息(single-frame) 其FIN置为1,并且opcode code 不是 0;
分片消息序列如下, 第一帧FIN置为0,opcode code不是0; 接着是FIN置为0,opcode code也是0; 最后帧 FIN为1,opcode code为0.
在分片消息发送期间可能插入了控制帧
控制帧不能分片
控制帧的opcode符号位为1, 目前控制帧包括 0×8(Close), 0×9(Ping) 0xA (Pong). 0xB-0xF 被预留。
    ws-frame                = frame-fin
frame-rsv1
frame-rsv2
frame-rsv3
frame-opcode
frame-masked
frame-payload-length
[ frame-masking-key ]
frame-payload-data
frame-fin               = %x0 ; 表示这不是当前消息的最后一帧,后面还有消息
/ %x1 ; 表示这是当前消息的最后一帧
frame-rsv1              = %x0
; 1 bit, 如果没有扩展约定,该值必须为0
frame-rsv2              = %x0
; 1 bit, 如果没有扩展约定,该值必须为0
frame-rsv3              = %x0
; 1 bit, 如果没有扩展约定,该值必须为0
frame-opcode            = %x0 ; 表示这是一个连续帧消息
/ %x1 ; 表示文本消息
/ %x2 ; 表示二进制消息
/ %x3-7 ; 保留
/ %x8 ; 表示客户端发起的关闭
/ %x9 ; ping(用于心跳)
/ %xA ; pong(用于心跳)
/ %xB-F ; 保留
frame-masked            = %x0 ; 数据帧没有加掩码,后面没有掩码key
/ %x1 ; 数据帧加了掩码,后面有掩码key
frame-payload-length    = %x00-7D
/ %x7E frame-payload-length-16
/ %x7F frame-payload-length-63
; 表示数据帧的长度
frame-payload-length-16 = %x0000-FFFF
; 表示数据帧的长度
frame-payload-length-63 = %x0000000000000000-7FFFFFFFFFFFFFFF
; 表示数据帧的长度
frame-masking-key       = 4( %0x00-FF ) ; 掩码key,只有当掩码位为1时出现
frame-payload-data      = (frame-masked-extension-data
frame-masked-application-data) 
                  ; 当掩码位为1时,这里的数据为带掩码的数据,扩展数据及应用数据都带掩码
/ (frame-unmasked-extension-data
frame-unmasked-application-data) ;
                 当掩码位为0时,这里的数据为不带掩码的数据,扩展数据及应用数据都不带掩码
frame-masked-extension-data     = *( %x00-FF ) ; 目前保留,以后定义
frame-masked-application-data   = *( %x00-FF )
frame-unmasked-extension-data   = *( %x00-FF ) ; 目前保留,以后定义
frame-unmasked-application-data = *( %x00-FF )
 
Close 处理

Close 帧的opcode是0×8. 接收到 Close 帧后,如果之前没发送过Close帧,则其必须发送Close 帧响应,但其可以延迟发送Close响应帧,例如在其发送完数据之后发送;但是,协议不保证对方在发送Close 帧后仍会处理其后续的数据。Close帧可能Client发起也可能是Server发起。
Ping-Pong 帧

接收到Ping帧后将响应Pong帧, 主要用于检测网络连接情况。
Extensions

WebSocket 支持协议扩展。 例如增加一个认证处理或者速率控制等,这通过client-server 协商完成。在WebSocket 握手处理时,通过头域Sec-WebSocket-Extensions来完成协商。 例如:
Sec-WebSocket-Extensions: mux; max-channels=4; flow-control,
deflate-stream
服务器接收一个或多个extensiions 通过再起响应的Sec-WebSocket-Extensions头域增加一个或多个extension完成。
 
说明:
 
服务器建立成功之后,如果有客户端请求连接本服务器,需要用socket_accept等方法建立一个新的socket连接,并接收客户端的请求信息,处理之后,返回响应信息,然后握手成功。 
接下来是字符串通信,客户端send过来一段字符串信息,服务器端接收到并返回给客户端这个字符串。   首先我们处理接收到的信息,根据上篇文章介绍的数据传输格式,并firefox的FIN一直为1,RSV1,2,3为0,如果是文本消息,那么 opcode为1,所以数据包的第一个数据是0x81,然后是一位mask值,firefox发来的数据是加了掩码的,所以mask值为1,后面跟7位是 数据信息长度,我们以客户端发送hi为例,那么长度就是2个字节,则第二个数据就是0x82,这里没有约定扩展数据,所以不存在扩展数据长度字节,接下来 是4个数据的掩码(因为我们这里是发送hi,2个字节的信息,小于125个字节,所以掩码是第3-第6个数据,根据数据长度的不同,掩码的位置也不同,如 果取到那7位表示的值是126,则掩码为第5-第8个数据,如果取到那7位表示的值是127,则掩码为第11-第14个数据),后面跟客户端发送的内容数 据,处理接收到的数据我们需要用取到的掩码依次轮流跟内容数据做异或(^)运算,第一个内容数据与第一个掩码异或,第二个内容数据与第二个掩码异或……第 五个内容数据与第一个掩码异或……以此类推,一直到结束,然后对内容进行编码。
 
举例:
 1 /// <summary>
 2 ///判断传入数据是否存在掩码
 3 /// 传入数据:hi
 4 /// socket接收到的二进制数据:
 5 ///      1000000110000010 1101011011101001
 6 ///      111110 111000 10111110 10000000
 7 /// 掩码异或的操作:
 8 ///             111110 111000 10111110 10000000
 9 ///   进行异或^ 111110 111001 11010110 11101001
10 ///    结果:                   1101000  1101001
11 /// 数据样例:
12 ///        [0]    129    byte
13 ///        [1]    130    byte
14 ///        [2]    214    byte
15 ///        [3]    233    byte
16 ///        [4]    62     byte
17 ///        [5]    56     byte
18 ///        [6]    190     byte
19 ///        [7]    128     byte
20 /// </summary>
21 /// <returns></returns>
22         private string UnWrap()
23         {
24             string result = string.Empty;
25
26             // 计算非空位置
27             int lastStation = GetLastZero();
28
29             // 利用掩码对org-data进行异或
30             int frame_masking_key = 1;
31             for (int i = 6; i <= lastStation; i++)
32             {
33                 frame_masking_key = i % 4;
34                 frame_masking_key = frame_masking_key == 0 ? 4 : frame_masking_key;
35                 frame_masking_key = frame_masking_key == 1 ? 5 : frame_masking_key;
36                 receivedDataBuffer[i] = Convert.ToByte(receivedDataBuffer[i] ^ receivedDataBuffer[frame_masking_key]);
37             }
38
39             System.Text.UTF8Encoding decoder = new System.Text.UTF8Encoding();
40             result = decoder.GetString(receivedDataBuffer, 6, lastStation - 6 + 1);
41
42             return result;
43
44         }
 
 
 WebSocket 协议:
 
public enum WebSocketProtocol
    {
        /*
         *
         * Request
            GET /WebIM5?uaid=200513807p8912-8de8c7e2-c963-4f67-8aca-8028797efbc1&re=0 HTTP/1.1
            Upgrade: WebSocket
            Connection: Upgrade
            Host: 10.10.150.60:5002
            Origin: https://localhost:444
            Sec-WebSocket-Key1: 3+3 1  8kgV"m 0 8  64u43
            Sec-WebSocket-Key2: 3_7891 6 4 `50 `8
         *
         * Response
            HTTP/1.1 101 WebSocket Protocol Handshake
            Upgrade: WebSocket
            Connection: Upgrade
            Sec-WebSocket-Origin: https://localhost:444
            Sec-WebSocket-Location: ws://192.168.110.....
            Sec-WebSocket-Protocol: WebIM5
         *
         *  asdfalskdfa
         * */
        draft_00 = 0,

/*
         *
         * Request
            GET /WebIM5?uaid=200513807p8912-2e695e5b-9b46-4511-b59e-28981b4ab327&re=0 HTTP/1.1
            Upgrade: websocket
            Connection: Upgrade
            Host: 10.10.150.60:5002
            Origin: https://localhost:444
            Sec-WebSocket-Key: 1o4Jk9XPGvTX66OxmNMaww==
            Sec-WebSocket-Version: 13
         *
         * Response
            HTTP/1.1 101 Switching Protocols
            Upgrade: websocket
            Connection: Upgrade
            Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
            Sec-WebSocket-Protocol: WebIM5
         * */
        draft_17 = 17
    }

转载于:https://www.cnblogs.com/lchb/articles/3324250.html

WebScoket 规范 + WebSocket 协议相关推荐

  1. Websocket协议的学习、调研和实现

    1. websocket是什么 Websocket是html5提出的一个协议规范,参考rfc6455. websocket约定了一个通信的规范,通过一个握手的机制,客户端(浏览器)和服务器(webse ...

  2. 【译】 WebSocket 协议第十二章——使用其他规范中的WebSocket协议

    概述 本文为 WebSocket 协议的第十二章,本文翻译的主要内容为如何使用其他规范中的 WebSocket 协议. 使用其他规范中的WebSocket协议(协议正文) WebSocket协议旨在由 ...

  3. websocket协议以及在gin中的应用

    目录 websocket协议简介 WebSocket 协议的来源 短轮询 本质 实现 应用场景 优缺点 长轮询 本质 实现 应用场景 优缺点 WebSocket协议 websocket定义及与HTPP ...

  4. 用node实现websocket协议

    协议 WebSocket是一种基于TCP之上的客户端与服务器全双工通讯的协议,它在HTML5中被定义,也是新一代webapp的基础规范之一. 它突破了早先的AJAX的限制,关键在于实时性,服务器可以主 ...

  5. 【译】 WebSocket 协议第十一章——IANA 注意事项(IANA Considerations)

    概述 本文为 WebSocket 协议的第十一章,本文翻译的主要内容为 WebSocket 的 IANA 相关注意事项. IANA 注意事项(协议正文) 11.1 注册新 URI 协议 11.1.1 ...

  6. websocket中发生数据丢失_tcp协议;websocket协议;同源策略和跨域

    tcp协议 为什么连接的时候是三次握手,关闭的时候却是四次握手? 答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文.其中ACK报文是用来应答的,SYN报 ...

  7. WebSocket协议探究(序章)

    一 WebSocket协议基于HTTP和TCP协议 与往常一样,进入WebSocket协议学习之前,先进行WebSocket协议抓包,来一个第一印象. WebSocket能实现客户端和服务器间双向.基 ...

  8. 【转】WebSocket协议:5分钟从入门到精通

    一.内容概览 由于WebSocket的出现,使得浏览器也具备了实时双向通信的能力.本文由浅入深,介绍了WebSocket建立连接.交换数据的细节,以及数据帧的格式.此外,还简要介绍了针对WebSock ...

  9. WebSocket协议入门介绍

    文章目录 WebSocket协议是什么 WebSocket是应用层协议 WebSocket与Http的区别 为什么要使用WebSocket 如何使用WebSocket 客户端API 在客户端使用Web ...

最新文章

  1. Android selector 使用注意.
  2. jvm性能调优实战 - 36XX:SoftRefLRUPolicyMSPerMB配置引起的Metaspace频繁FullGC
  3. 导轨式网管型工业交换机优势具体在哪里呢?
  4. Kubernetes 入门(4)集群配置
  5. Linux 应用程序 网络通讯函数记录
  6. 深入理解JVM(4)——对象内存的分配策略
  7. 下周见!Redmi K50标准版配置细节曝光:骁龙870+67W快充
  8. kali 开启ssh服务
  9. DucleBox | A Game Engine for OpenGL Programming
  10. 【leetcode】332. Reconstruct Itinerary
  11. 创建数独小游戏uniapp/vue
  12. Qt5下载安装及环境变量配置详解
  13. c盘中的软件怎么转到D盘,将c盘软件转移到d盘
  14. 10个低成本真实兼职,在家就能干的兼职有那些?
  15. ruoyi(若依)框架学习
  16. 互转(经纬度、地心坐标、东北天坐标)
  17. 记录一下,转换树结构数据
  18. (附源码)基于Python的“书怡”在线书店系统的设计与实现 毕业设计082332
  19. 高新技术企业八大领域分析
  20. 关于目标与执行力的思考

热门文章

  1. java流读写_java流概述以及文件读写示例
  2. 土木工程和计算机专硕,第一次发帖 关于大工土木专硕
  3. vs2019能写Java吗_Visual studio2019打包程序过程
  4. 《SpringCloud超级入门》使用Eureka集群搭建《十三》
  5. 火车头php接口制作,火车头接口
  6. 为什么计算机关机慢,电脑关机慢是什么原因 电脑关机慢的原因【图文】
  7. window10内核Linux,windows 10中发布完整的Linux内核
  8. 数据增强_imgaug图像数据增强必备工具
  9. 鸿蒙不是安卓也不是Linux
  10. python音频聚类_python实现鸢尾花三种聚类算法(K-means,AGNES,DBScan)