zoukankan      html  css  js  c++  java
  • Erlang二进制模式匹配

      Erlang的模式匹配用来处理二进制数据可谓是得心应手。不仅直观,而且超乎想象的简单。在C++中,处理二进制数据首先要管理缓冲区。然后再按字节进行操作,如果要处理的数据不是按字节对齐,则需要进行位移等操作。操作过程复杂又难懂,如果再没有注释,那对于维护这段代码的人来说简直就是噩梦。例如:操作一串保存了RGB颜色值序列的二进制串,在C++中要这样操作:

    struct RGB
    {
        char R;
        char G;
        char B;
    };
    
    vector<RGB> rgbVector;
    for(int i = 0; i < pixelsLen; i = i + 3)
    {
        RGB rgb;
        rgb.R = pixels[i];
        rgb.G = pixels[i + 1];
        rgb.B = pixels[i + 2];
        rgbVector.push_back(rgb);
    }

      首先要定义RGB结构,假设RGB数据流保存在pixels指向的地址中,然后通过循环解析出相应的RGB值,然后保存在数组中。而实现同等功能的Erlang却只需要一行就搞定,如下:

    Pixels = <<213,45,132,64,76,0,0,234,32,15>>.
    RGB = [ {R,G,B} || <<R:8,G:8,B:8>> <= Pixels ].

      是不是很简单,而且上面所举的例子中,RGB的值刚好是一个字节,所以在C++中处理方式相对比较简单。下面看一个更复杂的实例,这个例子在Erlang官方文档中有介绍,你可以戳这里.这是一个解析IP数据包头的例子(如果不了解IP包头戳这里),在Erlang中只需要这样:

    -define(IP_VERSION, 4).
    -define(IP_MIN_HDR_LEN, 5). 
    DgramSize = size(Dgram), 
    case Dgram of  
        <<?IP_VERSION:4, HLen:4, SrvcType:8, TotLen:16,  
          ID:16, Flgs:3, FragOff:13, 
          TTL:8, Proto:8, HdrChkSum:16, 
          SrcIP:32, 
          DestIP:32, RestDgram/binary>> when HLen>=5, 4*HLen=<DgramSize -> 
            OptsLen = 4*(HLen - ?IP_MIN_HDR_LEN), 
            <<Opts:OptsLen/binary,Data/binary>> = RestDgram, 
        ... 
    end.

      看到这段代码你是不是很容易得就明白了,它要干什么,各种值的位置、占用的空间大小以及所代表的意思都一目了然,看着真的是有一种心旷神怡的感觉。我第一次看到这样的处理方式时,我很激动,原来处理二进制数据可以如此简单直观。虽然简单易懂,但是我还是要在这里简单的介绍一下,首先通过size函数获取整个IP数据包的长度。然后对整个数据包进行二进制模式匹配。根据IP包头的格式,0-3位是协议版本号,对于IPV4来说这里应该是4,所以在模式匹配的时候直接<<4:4, Rest/binary>>就可以匹配到版本号了。上面的例子中把4定义成一个宏。接下来的4-7位是IP首部的长度。后面的我就不详细介绍了,具体IP头部参考这里。我在这里举这个例子并不是为了真的用Erlang去解析IP包,仅仅是为了说明Erlang解析二进制的优点。

      最后给一个我现在游戏服务器中包头的解析。包头由16位的包长度和16位的消息码组成,总共4个字节。解析的方式如下:
    <<DataLen:16,Command:16,RData/binary>> = Data

      其中Data是原始数据包,DataLen是包长度,Command是消息码,RData是包体。当然在实际项目中还要考虑粘包,半包以及相应的错误处理部分,这里仅仅提供了二进制模式匹配的方式。

  • 相关阅读:
    如何理解联合文件系统?
    Docker 学习笔记(一)
    Bzoj 3124: [Sdoi2013]直径 题解
    Bzoj 3131 [Sdoi2013]淘金 题解
    欧拉路(题目)
    硬币问题
    线段树、树状数组
    Splay树、Treap树
    模拟退火
    广搜题目(一本通)
  • 原文地址:https://www.cnblogs.com/kiven-code/p/3758050.html
Copyright © 2011-2022 走看看