使用erlang实现简单的二进制通信协议

最近实现的一种简单的协议以及工具,主要用于客户端服务端通讯传输二进制数据时,协议的解包与封包,具体如下:
首先定义协议的格式,主要由三部分组成:
        数据长度(数据部分长度+协议号长度):4个字节
        协议号:2个字节
        数据部分:2进制数据
数据部分如果是字符串需要先计算字符串的长度,占2个字节,之后再紧跟字符串内容,
以上三个部分构成一个完整的数据包,每次客户端服务端将数据进行以上格式的封包解包进行通信。
下面是对一个协议号为10000的协议进行封包的例子:
客户端向服务端发送了三个数据:角色rid(4个字节),服务器srv_id(字符串),消息msg(字符串),
根据以上定义的协议的打包方式如下,定义一个erlang函数:

pack(cli, 10000, {Rid, Srv_id, Msg}) ->
     Data   = <<Rid:32, byte_size(Srv_id):16, Srv_id/binary, byte_size(Msg):16, Msg/binary>>,
     Packet = <<(byte_size(Data) + 2):32, 10000:16, Data/binary>>,
     {ok, Packet}.

之后客户端可能通过socket的方式将二进制数据包发送给服务端了。

假设服务器收到数据,开始对数据包进行解析,
 P0表示一个完整的包的数据部分,且是上面客户端打包的数据,协议号为10000号,接下来就是将P0进行解包,
 对此我写了一个模块lib_proto,专门来解析二进制数据包。下面的解析过程就是针对协议号为10000的数据包进行解析:

unpack(srv, 10000, P0) ->
    {Rid, P1} = lib_proto:read_uint32(P0),
    {Srv_id, P2} = lib_proto:read_string(P1),
    {Msg, _P3} = lib_proto:read_string(P2),
    {ok, {Rid, Srv_id, Msg}}.

通过上面的方式就能将数据包解析出来,得到各个字段的值。
下面是lib_proto的部分实现:

read_uint32(B0) when is_binary(B0)
        andalso byte_size(B0) >= 4 ->
    <<Int32:32, B1/binary>> = B0,
    {Int32, B1};
read_uint32(_B0) -> error.

read_string(B0) when is_binary(B0)
        andalso byte_size(B0) >= 2 ->
    <<Len:16, B1/binary>> = B0,
    case byte_size(B1) >= Len of
        true ->
            <<String:Len/binary, B2/binary>> = B1,
            {String, B2};
        false ->
            error
    end;
read_string(_B0) -> error.

以上就是使用erlang进行二进制数据包的解包与封包的应用,应该说erlang生来就对处理二进制数据进行了很好的封装,
个人只是在此基础上进行简单应用而已。

时间: 2024-12-20 07:43:46

使用erlang实现简单的二进制通信协议的相关文章

Erlang 位串和二进制数据

http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=25876834&id=3300393 因为在本人工作中,服务端Erlang和客户端的flash通信都是发送二进制数据(协议)来通信,Erlang处理起来二进制数据真的很方便,在空余时间查看和翻译了Erlang的二进制相关一些说明文档,当然里面也有根据自己的经验和知识理解的地方. 在二进制解析部分,其实还有很多好的例子.还有就是Erlang的二进制实际应用的例子,下次会再分享的,

ejabberd,erlang,简单看了一下,总结一下,很肤浅

本来也没打算深入学习erlang,就是看一下他们的大概思路erlang每个自定义函数都能注册成进程,每个节点通过erl -name '[email protected]'.进去后,可以直接做远程调用,节点之间就靠一个连接,来回传输,如果想再开一个了连接我估计是可以的吧,不太清楚,这个无所谓,一个就够了,可以随便登录某台节点并执行其他节点上的进程,前提是进程注册一下. ejabberd通过xmpp协议,集群里有多台机器,每个机器都有一份路由表,这个用来找到你想发送数据的目的机器目的进程等等,每次建

简单模拟二进制求和

题目: 给定两个二进制字符串,返回他们的和(用二进制表示). 样例 a = 11 b = 1 返回 100 代码: #include<bits/stdc++.h> using namespace std; const int maxn=1e3+5; char a[maxn],s1[maxn],s2[maxn]; int main() { scanf("%s",s1); scanf("%s",s2); int len1=strlen(s1); int le

一个简单的二进制加法器

先用C++随便声明一个bit结构体: struct bit { unsigned char bit_value; bit(unsigned int value){ if (value == 0 || value == 1) bit_value = (unsigned char)value; else bit_value = 0; } bit() { bit_value = 0; } }; 一位与一位的加法称为半加器,因为不考虑后面的进位加进来: //sumbit表示加法位,carrybit表示进

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

通信协议之序列化

原文转自:http://blog.chinaunix.net/uid-27105712-id-3266286.html 通信协议可以理解两个节点之间为了协同工作实现信息交换,协商一定的规则和约定,例如规定字节序,各个字段类型,使用什么压缩算法或加密算法等.常见的有tcp,udo,http,sip等常见协议.协议有流程规范和编码规范.流程如呼叫流程等信令流程,编码规范规定所有信令和数据如何打包/解包. 编码规范就是我们通常所说的编解码,序列化.不光是用在通信工作上,在存储工作上我们也经常用到.如我

Erlang 转至维基百科

Erlang(英语发音:/??rlæ?/)是一种通用的并行程序设计语言,它由乔·阿姆斯特朗(Joe Armstrong)在瑞典电信设备制造商爱立信所辖的计算机科学研究室开发,目的是创造一种可以应付大规模开发活动的程序设计语言和运行环境.Erlang于1987年发布正式版本,最早是爱立信拥有的私有软件,经过十年的发展,于1998年发表开放源代码版本. Erlang是运作于虚拟机的解释型语言,但是现在也包含有乌普萨拉大学高性能Erlang计划(HiPE)[2]开发的原生代码编译器,自R11B-4版本

Erlang学习笔记2

http://wgcode.iteye.com/blog/1007623 第二章 入门 1.所有的变量都必须以大写字母开头,如果要查看某个变量,只要输入变量的名字即可,如果一个变量被赋予值,就称为绑定变量,否则被称为自由变量,一开始所有变量都是自由的. 有一点像Java中的常量,这就是为什么用大写字母的原因. 2.  “=” 近似于一个赋值操作符,是一个模式匹配运算符,当X是自由变量未被赋值时“=”是赋值运算符,否则是模式匹配运算符. 3. “/”除号永远返回浮点数. 4. 原子用来表示不同的非

erlang note

没有关于erlang interface ,继续寻找吧... ----------------------------------------------------------------- http://wgcode.iteye.com/blog/1018614 第二章 入门 1.所有的变量都必须以大写字母开头,如果要查看某个变量,只要输入变量的名字即可,如果一个变量被赋予值,就称为绑定变量,否则被称为自由变量,一开始所有变量都是自由的. 有一点像Java中的常量,这就是为什么用大写字母的原