码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-01-30 22:26:41      阅读:443      评论:0      收藏:0      [点我收藏+]

标签:

最近实现的一种简单的协议以及工具,主要用于客户端服务端通讯传输二进制数据时,协议的解包与封包,具体如下:
首先定义协议的格式,主要由三部分组成:
        数据长度(数据部分长度+协议号长度):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生来就对处理二进制数据进行了很好的封装,
个人只是在此基础上进行简单应用而已。

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

标签:

原文地址:http://www.cnblogs.com/bicowang/p/4263227.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!