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是包体。当然在实际项目中还要考虑粘包,半包以及相应的错误处理部分,这里仅仅提供了二进制模式匹配的方式。

Erlang二进制模式匹配,布布扣,bubuko.com

时间: 2024-08-07 21:20:45

Erlang二进制模式匹配的相关文章

[原创]erlang二进制语法点滴

Erlang/OTP 17 [erts-6.0] [source] [smp:2:2] [async-threads:10] [kernel-poll:false]Eshell V6.0  (abort with ^G)1> <<100,200,300,400>>.<<100,200,44,144>>2> <<100,200,300:16,400:16>>.<<100,200,1,44,1,144>>

erlang二进制数据垃圾回收机制

erlang二进制数据在内存中有两种存在形式,当数据大小不到 64 bytes,就直接存在进程堆内.假设超过了64 bytes.就被保存到进程外的共享堆里,能够给节点内全部进程共享. erlang有两种二进制容器:heap binaries和refc binaries. heap binaries Heap binaries are small binaries, up to 64 bytes, that are stored directly on the process heap. They

Effective Erlang —— 二进制型的构造和匹配

在 R12B 中,构造和匹配二进制型最自然的方式比前版中的要快得多.你可用如下简单的代码来构造一个二进制型: 这么写(在 R12B 中)/求别这么写(在 R12B 之前的版本中) my_list_to_binary(List) -> my_list_to_binary(List, <<>>). my_list_to_binary([H|T], Acc) -> my_list_to_binary(T, <<Acc/binary,H>>); my_l

Erlang 摘要

世界是并行的,Erlang程序反应了我们思考和交流的方式,人作为个体通过发送消息进行交流,如果有人死亡,其他人会注意到.Erlang里的模块类相当于OOPL中的类,进程相当于OOPL里的对象或类实例.并发编程可以用来提升性能,创建可扩展和容错的系统,以及编写清晰和可理解的程序来控制现实世界里的应用. 并发程序是以一种并发编程语言编写的程序,并发编程语言拥有用于编写并发程序的语言结构.Erlang的并发程序是由互相通信的多组顺序进程组成,一个进程就是一个轻量级的虚拟机,可以执行单个的Erlang函

Erlang 杂记

学习Erlang的时候在书的留白处随手记录了一些东西,还有一些记录在了demo的注释里面,今天抽时间整理出来了一部分,分享一下. Erlang的设计哲学是为每一个独立的事件创建一个新进程. Erlang的容错处理:如果不能完成一个任务就死掉 让其它正常的进程来善后.link函数就是用来建立这种进程间的双向连接来监测非正常退出,并做出处理. BIFs是built-in functions的缩写代表这些方法是Erlang运行时系统的一部分 side-effect-free无副作用,其中一种定义是说:

Erlang入门(一)

读erlang.org上面的Erlang Course四天教程1.数字类型,需要注意两点1)B#Val表示以B进制存储的数字Val,比如 7> 2#101.5 二进制存储的101就是10进制的5了2)$Char表示字符Char的ascii编码,比如$A表示65 2.比较难以翻译的概念——atom,可以理解成常量,它可以包含任何字符,以小写字母开头,如果不是以小写字母开头或者是字母之外的符号,需要用单引号包括起来,比如abc,'AB' 3.另一个概念——Tuple,有人翻译成元组,可以理解成定长数

Erlang中的基本元素操作

Erlang shell中,用句号加空格.tab或回车来结束表达式,%表示注释的起点,;隔离子句.模块是.erl 文件,库的头文件.hrl, shell中的编译时c(),外编译命令时erlc, 退出shell用q(),或erlang:halt(). 变量以大写字母开头,且不能重新绑定变量,只能一次性赋值,具有不可变状态. 原子是全局的,不需要宏定义或包含文件,以小写字母开头,还可放在单引号内,是极简表达式. 元组tuple是一些数量固定的项目归组成单一实体{,}, 由于是匿名的,通常在第一个元素

Erlang与C构建的节点通讯

Erlang节点之间的通讯,主要用于两个Erlang节点之间的通讯,但Erlang还支持与java构建的节点通讯,甚至与c构建的节点通讯,前面两种方式在我以前的文章都有讲到,所以这里讲Erlang与c构建的节点通讯. Cnode与erl_interface 想用C构建一个erlang节点,要利用Erlang的erl_interface接口来实现.c建立的节点,叫CNode ,其中,erl_interface除了实现一些基本的节点连接,消息发送接收,还实现Erlang Term 的构建解析. CN

erlang的优缺点

Erlang的优势与缺陷  Erlang在消息执行方式上的优势在于灵活.Erlang是弱类型语言,在实现的时候可以任意调整消息的内容,或是模式的要求.在 Erlang进行模式匹配时往往有种约定:使用“原子”来表示“做什么”,而使用“绑定”来获取操作所需要的“数据”,这种方式避免了冗余的cast和赋 值,在使用的时候颇为灵活.然而,世上没有完美的事物,Erlang的消息执行方式也有缺陷,而且是较为明显的缺陷.  首先,Erlang的数据抽象能力实在太弱.如果编写一个略显复杂的应用程序,您会发现程序