其实我一直想不明白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.1
Connection:Upgrade
Host:127.0.0.1:8088
Origin:null
Sec-WebSocket-Extensions:x-webkit-deflate-frame
Sec-WebSocket-Key:puVOuWb7rel6z2AVZBKnfw==
Sec-WebSocket-Version:13
Upgrade: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 Protocols
Connection:Upgrade
Server:beetle websocket server
Upgrade:WebSocket
Date:Mon, 26 Nov 2012 23:42:44 GMT
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:content-type
Sec-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数据包协议详解的更多相关文章

  1. IP数据包格式详解(转)

    摘自:http://blog.163.com/hlz_2599/blog/static/1423784742011112195857956/</> TCP/IP协议定义了一个在因特网上传输 ...

  2. TCP/IP数据包结构详解

    一般来说,网络编程我们只需要调用一些封装好的函数或者组件就能完成大部分的工作,但是一些特殊的情况下,就需要深入的理解网络数据包的结构,以及协议分析.如:网络监控,故障排查等…… IP包是不安全的,但是 ...

  3. WebSocket协议详解及应用

    WebSocket协议详解及应用(七)-WebSocket协议关闭帧 本篇介绍WebSocket协议的关闭帧,包括客户端及服务器如何发送并处理关闭帧.关闭帧错误码及错误处理方法.本篇内容主要翻译自RF ...

  4. TCP协议粘包问题详解

    TCP协议粘包问题详解 前言 在本章节中,我们将探讨TCP协议基于流式传输的最大一个问题,即粘包问题.本章主要介绍TCP粘包的原理与其三种解决粘包的方案.并且还会介绍为什么UDP协议不会产生粘包. 基 ...

  5. Web协议详解与抓包实战,高效解决网络难题

    无论你是前后端工程师,还是运维测试,如果想面试更高的职位,或者要站在更高的角度去理解技术业务架构,并能在问题出现时快速.高效地解决问题,Web 协议一定是你绕不过去的一道坎. 旨在帮助你对各种常用 W ...

  6. 接口测试之HTTP协议详解

    引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1. ...

  7. OSPF协议详解

    CCNP OSPF协议详解 2010-02-24 20:30:22 标签:CCNP 职场 OSPF 休闲 OSPF(Open Shortest Path Fitst,ospf)开放最短路径优先协议,是 ...

  8. RTMP协议详解(转)

    转自<RTMP协议详解(一) (二) (三) > Real Time Messaging Protocol(实时消息传送协议协议)是Adobe Systems公司为Flash播放器和服务器 ...

  9. TCP/IP协议详解概述

    TCP/IP协议详解卷1--第一章概述--读书笔记 作者:vpoet 日期:2015/06/25 注:本系列的文章只是作者对TCP/IP协议的理解,难免会出现纰漏或者不完整,当然也有可能很肤浅,希望大 ...

随机推荐

  1. win10环境下python3.5安装步骤

    点我去Python官网下载 往下翻几页就能看到各种版本的Python,当前最新的是Python3.6,也没多大区别,我选择的是3.5.2 64位的,点击download 根据自己的电脑配置,我选择的是 ...

  2. [CSS3]学习笔记-文字与字体相关样式

    1.给文字添加阴影 <!doctype html> <html> <head> <meta charset="utf-8"> < ...

  3. Java异常处理机制以及try-catch-finally-return执行顺序

    一,简单描述: 当出现程序无法控制的外部环境问题(用户提供的文件不存在,文件内容损坏,网络不可用...)时,JAVA就会用异常对象来描述. 二,JAVA中用2种方法处理异常: 1.在发生异常的地方直接 ...

  4. 【死磕Java并发】-----Java内存模型之happend-before

    在上篇博客([死磕Java并发]-–深入分析volatile的实现原理)LZ提到过由于存在线程本地内存和主内存的原因,再加上重排序,会导致多线程环境下存在可见性的问题.那么我们正确使用同步.锁的情况下 ...

  5. 基于Selenium2+Java的UI自动化(6)-操作Alert、confirm、prompt弹出框

    alert.confirm.prompt这样的js对话框在selenium1 时代处理起来比价麻烦,常常要用autoit来帮助处理.而现在webdriver对这些弹出框做了专门的处理,使用seleni ...

  6. Gulp自动构建Web前端程序

    这两天在一个朋友在项目上碰到了一个这样的问题,在运营过程中,用户在浏览器上对某个表单进行数据提交时,需要引入新的平台接口数据的业务,通过评估,开发团队马上修改了相关后台代码和部分的前端脚本代码,通过简 ...

  7. 读书笔记 effective c++ Item 24 如果函数的所有参数都需要类型转换,将其声明成非成员函数

    1. 将需要隐式类型转换的函数声明为成员函数会出现问题 使类支持隐式转换是一个坏的想法.当然也有例外的情况,最常见的一个例子就是数值类型.举个例子,如果你设计一个表示有理数的类,允许从整型到有理数的隐 ...

  8. 了解 : angular ng-messages

    ng-messages="form['positionTitle' + languageVersion.typeEnum].$error ng-messages="form.pos ...

  9. [TPYBoard-Micropython之会python就能做硬件 7] 学习使用蓝牙模块及舵机

    转载请注明:@小五义 http://www.cnblogs.com/xiaowuyi            欢迎加入讨论群 64770604 一.实验器材 1.TPYboard V102板  一块 2 ...

  10. Hibernate框架注解

    1.使用Hibernate注解的步骤                1.添加jar包                            Hibernate-annotations.jar      ...