zoukankan      html  css  js  c++  java
  • websocket+probuf.原理篇

    1、WebSocket  

      WebSocket,大家都知道,既然名字包含Socket,那么和Socket肯定差别不大,对,你没有搞错,的确差别不大。

      在网络编程中,我们一般的协议都是基于TCP/IP,WebSocket也不例外。和HTTP一样,他也有自己的头部和具体的数据而已。

    来看看。

    这是一个,websocket发起的连接,首先一个http的请求,告诉服务器,我要发送WebSocket的连接,服务器,返回一段ok.后面就可以继续使用这个连接,进行基本的WebSocket请求了。

    其实,WebSocket和普通的Socket没啥差别,都是send,receive,收发数据,只是数据的格式化需要特殊处理一下。下面来说明一下。

    WebSocket的发送的数据格式(接收和发送是一样的):

      来张网图:

      来段网文:解释一下:

    • FIN,指明Frame是否是一个Message里最后Frame(之前说过一个Message可能又多个Frame组成)
    • RSV1-3必须是0,除非有扩展定义了非零值的意义。
    • Opcode这个比较重要,有如下取值是被协议定义的
      • %x0 denotes a continuation frame

      • %x1 表示一个text frame

      • %x2 表示一个binary frame

      • %x3-7 are reserved for further non-control frames

      • %x8 表示连接关闭

      • %x9 表示 ping (心跳检测相关,后面会讲)

      • %xA 表示 pong (心跳检测相关,后面会讲)

      • %xB-F are reserved for further control frames

    • Mask,这个是指明“payload data”是否被计算掩码。这个和后面的Masking-key有关(如果=0,不需要计算结果:结果明文,如果是=1,name就配合后面四个字节的masking-key,来处理解码操作。字节按位异或,四个一次循环。)

          if(mask == 1){ 

           byte[] payload = xxxx; // 这里假设已经得到

                byte[] mask_key = new byte[4];// 这里假设已经得到

                for(int i=0;i<payload.Count;i++){

                       payload[i] = (byte)(payload[i] ^ mask_key[i%4]);

                }

                // 这样就可以解码出来明文了

          }else{

                // 明文的情况,2字节后面或者4字节,12字节后面就是具体的数据了,(真实情况,根据具体的数据来)。

        }

    • Payload len,数据的总长度,有三种情况[<126,>126 && <= 65535,> 65535], 这三种情况,占位不同,第一种,默认占位(它本身),(后续字节是数据或者masking-key(mask为1才有masking-key))
    • Masking-key,加密作用
    • Payload data,帧真正要发送的数据,可以是任意长度,但尽管理论上帧的大小没有限制,但发送的数据不能太大,否则会导致无法高效利用网络带宽,正如上面所说Websocket提供分片。
      是不是,瞬间就完了,没错,到这里其实就差不多了。如果你自己要加密数据,mask可以写死成一个值或者随机出来,反正都是4个字节而已。
      

      2、Probuf

      我们网络中常常会对数据进行编码然后传输,一般我们回用到的一些方式 content原文,xml,json,还有就是我们呼之欲出的probuf了。

      这种编码有什么好处呢,大大减少了网络带宽的消耗,同时减少了了数据解析的时间损耗。

    再来一波网图吧,数据的排列规则。

      图1:

      明显,这里就可以看出来,Tag占用一个位置,length占用一个位置,一般情况,如果是数据很长,namelength就可能占用多个字节了。根据length的首位判定。(length也是第一位是标识是否需要第二个直接加入计算,一次类推,这里解释一下:

    Varint:一种,把首位,作为判断条件,来对length进行计算的方式。

      0-0111 1111,一个字节可以表示范围: [0,0x7f]的大小,

          1000 0000 - 0000 0001 ----- 1111 1111 - 0111 1111 , 二个字节可以表示范围:[1<<7, 0x7f<<7 + 0x7f]
          1000 0000 - 0000 0000 - 0000 0001 ----- 1111 1111 - 1111 1111 - 0111 1111 , 三个字节可以表示范围:[1 << 7 * 2,  0x7f<<7 <<7 + 0x7f<<7 + 0x7f]

      这样一般来说,就只需要小部分直接寄可以处理大部分数据了。

      所以诞生了probuf的说明或者解析文件:(来个栗子)

    message DownStreamMessages {
        repeated DownStreamMessage list = 1;
        required int64 syncTime = 2;
        optional bool finished = 3;
    }
    
    message DownStreamMessage {
    required string fromUserId = 1;
    required ChannelType type = 2;
    optional string groupId = 3;
    required string classname = 4;
    required bytes content = 5;
    required int64 dataTime = 6;
    required int64 status = 7;
    optional int64 extra = 8;
    optional string msgId = 9;
    optional int32 direction = 10;
    optional int32 plantform =11;
    optional int32 isRemoved = 12;
    optional string source = 13;
    optional int64 clientUniqueId = 14;
    optional string extraContent = 15;
    }
    
    enum ChannelType {
    PERSON = 1;
    PERSONS = 2;
    GROUP = 3;
    TEMPGROUP = 4;
    CUSTOMERSERVICE = 5;
    NOTIFY = 6;
    MC=7;
    MP=8;
    }

    这里面有几个关键字需要处理一下:(bool和enum都是作为整数处理即可),字段后面的  = 1;  = 2 表面这个的filed_number.值。

      required  一般都是必须的

           optional 非必须的

           repeated 重复的,一个表示集合。

            

      网图奉上:

          

                        编码数据长度。

                         

      上图就是数据的 排列规则了,数据比较紧凑。

      特别说明repeat的情况,repeat后面的length是指读取这个需要用到的字节数。而不是重复的个数。

           参考:https://juejin.im/post/6844903582290935822

      参考:https://blog.csdn.net/carson_ho/article/details/70568606

      参考:https://blog.csdn.net/JMW1407/article/details/107197938/

     

  • 相关阅读:
    WinAPI: ExtractIcon 获取 EXE、DLL 或 ICO 文件中的图标
    WinAPI: LoadLibrary、FreeLibrary 载入与载卸模块
    WinAPI: LoadCursor 从资源中载入光标
    WinAPI: LoadIcon 从资源中载入图标
    WinAPI: LoadString 从资源中载入字符串
    学习使用资源文件[9] WAVE 资源
    学习使用资源文件[11] DLL 中的资源文件
    WinAPI: LoadBitmap 从资源中载入位图
    学习使用资源文件[10] 嵌入和提取任何类型的文件
    肛男四代
  • 原文地址:https://www.cnblogs.com/Supperlitt/p/13941882.html
Copyright © 2011-2022 走看看