WebSocket数据包协议详解
其实我一直想不明白HTML5包装个应用层办议作为Socket通过基础目的是为了什么,其实直接支持Socket tcp相对来说更加简单灵活.既然标准已经制定而浏览器也支持那对于我们开发者来说只能用的分.最新版本的WebSocket协议于2011-12其标准规范已经明确下来,所以现在可以根据这标准进行相应的开发.详细参考http://datatracker.ietf.org/doc/rfc6455/?include_text=1
WebSocket协议主要分为两部分,第一部分是连接许可验证和验证后的数据交互.连接许可验证比较简单,由Client发送一个类似于HTTP的请求,服务端获取请求后根据请求的KEY生成对应的值并返回.
连接请求内容:
|
1
2
3
4
5
6
7
8
|
GET / HTTP/1.1Connection:UpgradeHost:127.0.0.1:8088Origin:nullSec-WebSocket-Extensions:x-webkit-deflate-frameSec-WebSocket-Key:puVOuWb7rel6z2AVZBKnfw==Sec-WebSocket-Version:13Upgrade:websocket |
服务端接收请求后主要是成针对Sec-WebSocket-Key生成对就Sec-WebSocket-Accept 的key,生成Sec-WebSocket-Accept 值比较简单就是Sha1(Sec-WebSocket-Key+258EAFA5-E914-47DA-95CA-C5AB0DC85B11)即可,C#代码如下:
|
1
2
3
4
5
|
SHA1 sha1 = new SHA1CryptoServiceProvider();byte[] bytes_sha1_in = Encoding.UTF8.GetBytes(request.SecWebSocketKey+ "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");byte[] bytes_sha1_out = sha1.ComputeHash(bytes_sha1_in);string str_sha1_out = Convert.ToBase64String(bytes_sha1_out);response.SecWebSocketAccept = str_sha1_out; |
服务端返回内容:
|
1
2
3
4
5
6
7
8
|
HTTP/1.1 101 Switching ProtocolsConnection:UpgradeServer:beetle websocket serverUpgrade:WebSocketDate:Mon, 26 Nov 2012 23:42:44 GMTAccess-Control-Allow-Credentials:trueAccess-Control-Allow-Headers:content-typeSec-WebSocket-Accept:FCKgUr8c7OsDsLFeJTWrJw6WO8Q= |
经过服务器的返回处理后连接握手成功,后面就可以进行TCP通讯.WebSocket在握手后发送数据并象下层TCP协议那样由用户自定义,还是需要遵循对应的应用协议规范...这也是在文章之说没有直接基于Socket tcp方便的原因.
数据交互协议:
这图有点难看懂...里面包括几种情况有掩码,数据长度小于126,小于UINT16和小于UINT64等几种情况.后面会慢慢详细说明.整个协议头大概分三部分组成,第一部分是描述消息结束情况和类型,第二部分是描述是否存在掩码长度,第三部分是扩展长度描述和掩码值.
从图中可以看到WebSocket协议数据主要通过头两个字节来描述数据包的情况
第一个字节
最高位用于描述消息是否结束,如果为1则该消息为消息尾部,如果为零则还有后续数据包;后面3位是用于扩展定义的,如果没有扩展约定的情况则必须为0.可以通过以下c#代码方式得到相应值
|
1
|
mDataPackage.IsEof = (data[start] >> 7) > 0; |
最低4位用于描述消息类型,消息类型暂定有15种,其中有几种是预留设置.c#代码可以这样得到消息类型:
|
1
2
|
int type = data[start] & 0xF;mDataPackage.Type = (PackageType)type; |
第二个字节
消息的第二个字节主要用一描述掩码和消息长度,最高位用0或1来描述是否有掩码处理,可以通过以下c#代码方式得到相应值
|
1
|
bool hasMask = (data[start] >>7) > 0; |
剩下的后面7位用来描述消息长度,由于7位最多只能描述127所以这个值会代表三种情况,一种是消息内容少于126存储消息长度,如果消息长度少于UINT16的情况此值为126,当消息长度大于UINT16的情况下此值为127;这两种情况的消息长度存储到紧随后面的byte[],分别是UINT16(2位byte)和UINT64(4位byte).可以通过以下c#代码方式得到相应值
|
1
2
3
4
5
6
7
8
9
10
11
12
|
mPackageLength = (uint)(data[start] & 0x7F);start++;if (mPackageLength == 126){ mPackageLength = BitConverter.ToUInt16(data, start); start = start + 2;}else if (mPackageLength == 127){ mPackageLength = BitConverter.ToUInt64(data, start); start = start + 8;} |
如果存在掩码的情况下获取4位掩码值:
|
1
2
3
4
5
6
7
8
|
if (hasMask){ mDataPackage.Masking_key = new byte[4]; Buffer.BlockCopy(data, start, mDataPackage.Masking_key, 0, 4); start = start + 4; count = count - 4;} |
获取消息体
当得到消息体长度后就可以获取对应长度的byte[],有些消息类型是没有长度的如%x8 denotes a connection close.对于Text类型的消息对应的byte[]是相应字符的UTF8编码.获取消息体还有一个需要注意的地方就是掩码,如果存在掩码的情况下接收的byte[]要做如下转换处理:
|
1
2
3
4
5
6
|
if (mDataPackage.Masking_key != null) { int length = mDataPackage.Data.Count; for (var i = 0; i < length; i++) mDataPackage.Data.Array[i] = (byte)(mDataPackage.Data.Array[i] ^ mDataPackage.Masking_key[i % 4]); } |
WebSocket数据包协议详解的更多相关文章
- IP数据包格式详解(转)
摘自:http://blog.163.com/hlz_2599/blog/static/1423784742011112195857956/</> TCP/IP协议定义了一个在因特网上传输 ...
- TCP/IP数据包结构详解
一般来说,网络编程我们只需要调用一些封装好的函数或者组件就能完成大部分的工作,但是一些特殊的情况下,就需要深入的理解网络数据包的结构,以及协议分析.如:网络监控,故障排查等…… IP包是不安全的,但是 ...
- WebSocket协议详解及应用
WebSocket协议详解及应用(七)-WebSocket协议关闭帧 本篇介绍WebSocket协议的关闭帧,包括客户端及服务器如何发送并处理关闭帧.关闭帧错误码及错误处理方法.本篇内容主要翻译自RF ...
- TCP协议粘包问题详解
TCP协议粘包问题详解 前言 在本章节中,我们将探讨TCP协议基于流式传输的最大一个问题,即粘包问题.本章主要介绍TCP粘包的原理与其三种解决粘包的方案.并且还会介绍为什么UDP协议不会产生粘包. 基 ...
- Web协议详解与抓包实战,高效解决网络难题
无论你是前后端工程师,还是运维测试,如果想面试更高的职位,或者要站在更高的角度去理解技术业务架构,并能在问题出现时快速.高效地解决问题,Web 协议一定是你绕不过去的一道坎. 旨在帮助你对各种常用 W ...
- 接口测试之HTTP协议详解
引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1. ...
- OSPF协议详解
CCNP OSPF协议详解 2010-02-24 20:30:22 标签:CCNP 职场 OSPF 休闲 OSPF(Open Shortest Path Fitst,ospf)开放最短路径优先协议,是 ...
- RTMP协议详解(转)
转自<RTMP协议详解(一) (二) (三) > Real Time Messaging Protocol(实时消息传送协议协议)是Adobe Systems公司为Flash播放器和服务器 ...
- TCP/IP协议详解概述
TCP/IP协议详解卷1--第一章概述--读书笔记 作者:vpoet 日期:2015/06/25 注:本系列的文章只是作者对TCP/IP协议的理解,难免会出现纰漏或者不完整,当然也有可能很肤浅,希望大 ...
随机推荐
- 2017年Unity开发环境与插件配置安装(总体介绍)
最近(2017年初)有朋友问,Unity客户端开发如何在机器配置一般的情况下,配置更高效的开发环境,进一步加快开发进度. 推荐如下: Win10(或者Win8)+Unity5.5.1版本(2017年2 ...
- js精要之模块模式
// 模块模式是一种用于创建拥有私有数据的单件对象的模式,基本做法是使用立调函数(IIFE)来返回一个对象 var yourObjet = (function(){ // 私有数据 return { ...
- Vuex核心知识(2.0)
Vuex 是一个专门为 Vue.js 应该程序开发的状态管理模式,它类似于 Redux 应用于 React 项目中,他们都是一种 Flux 架构.相比 Redux,Vuex 更简洁,学习成本更低.希望 ...
- window nfs 服务端配置安装
windows7下面安装nfs客户端命令(首先开启windows客户端mount挂载命令): 打开或关闭windows功能>nfs服务(勾选上)重启 windows nfs共享有两种方式分别 ...
- shell变量数学运算
shell变量数学运算 #!/bin/sh # 本脚本说明shell脚本中变量运算的用法 # 错误的用法var=1var=$var+1echo $var 输出:1+1 # 第一种用法,letvar=1 ...
- Windows 10 IoT Serials 6 - 如何修改IoTStartupOnBoot.cmd文件
使用Windows 10 IoT Core系统的朋友应该会比较熟悉IoTStartupOnBoot.cmd文件,该文件是系统启动以后加载的批处理文件,一般会包含应用.服务和后台的启动,比如WinRM. ...
- 可能是一份没什么用的爬虫代理IP指南
写在前面 做爬虫的小伙伴一般都绕不过代理IP这个问题. PS:如果还没遇到被封IP的场景,要不就是你量太小人家懒得理你,要不就是人家压根不在乎... 爬虫用户自己是没有能力维护一系列的代理服务器和代理 ...
- 运行gpg --gen-key生成key时出现卡住的问题
背景 在搭建Ubuntu16.04的本地apt源时,需要运行"gpg --gen-key"命令,但是在执行该命令时,出现了:"Not enough random byte ...
- shell基础学习系列(一)
打开文本编辑器,新建一个文件,扩展名为sh(sh代表shell),扩展名并不影响脚本执行. 输入一些代码: #!/bin/bash echo "Hello World !" &qu ...
- 编程思想之——"人是活的,程序是死的"
"人是活的,程序是死的"这句话我时常提起,可能很多人不是很理解我为什么会这样说,下面我就简单来谈谈我对这句话的理解. 1.不要因为技术而技术,技术选型的初衷是需求. 现在很多人在做 ...