简单实现了下memcached binary protocol的 get和 set command,体验了下erlang binary语法的强大和方便
代码:
-module(binary_server).
-export([start/0]).
start() ->
{ok,Listen}=gen_tcp:listen(7777,[binary,{packet,0},{reuseaddr,true},{active,true}]),
register(kvs,spawn(fun() -> dict() end)),
accept(Listen).
accept(Listen) ->
{ok,Socket}=gen_tcp:accept(Listen),
spawn(fun() -> accept(Listen) end),
inet:setopts(Socket,[binary,{packet,0},{active,true}]),
process(Socket,<<>>).
process(Socket,Left) ->
receive
{tcp,Socket,Bin} ->
Buffer=list_to_binary(binary_to_list(Left) ++ binary_to_list(Bin)),
case regonized(Buffer) of
{save_ok,RealRemaning} ->
Resp=[16#81,16#1] ++ fill_all(0,22,[]),
gen_tcp:send(Socket,list_to_binary(Resp)),
process(Socket,RealRemaning);
{get_ok,undefined,Remaining} ->
Value= <<"not_found">>,
BodyLen=length(binary_to_list(Value))+4,
Resp=[16#81] ++ fill_all(0,3,[]) ++[16#4]
++ fill_all(0,3,[]) ++
binary_to_list(<<BodyLen:32>>) ++
binary_to_list(<<0:128>>) ++
binary_to_list(Value),
gen_tcp:send(Socket,list_to_binary(Resp)),
process(Socket,Remaining);
{get_ok,{ok,Value},Remaining} ->
BodyLen=length(binary_to_list(Value))+4,
Resp=[16#81] ++ fill_all(0,3,[]) ++[16#4]
++ fill_all(0,3,[]) ++
binary_to_list(<<BodyLen:32>>) ++
binary_to_list(<<0:128>>) ++
binary_to_list(Value),
gen_tcp:send(Socket,list_to_binary(Resp)),
process(Socket,Remaining);
{get_timeout,Remaining} ->
process(Socket,Remaining);
{not_engouh_streams} ->
process(Socket,Buffer)
end;
{tcp_closed,Socket} ->
io:format("peer closed~n")
end.
regonized(Buffer) ->
case Buffer of
%%set command
<<16#80:8,16#1:8,KeyLen:16/big,
ExtraLen:8/big,DataType:8,Reserved:16/big,
BodyLen:32/big,Opaque:32/big,Cas:64/big,
Extras:64/big,Key:KeyLen/big-binary-unit:8,
Remaning/binary>> ->
ValueLen=BodyLen-KeyLen-ExtraLen,
case Remaning of
<<Value:ValueLen/binary-unit:8,
RealRemaning/binary>> ->
%% got completed packet,deal with set command
kvs ! {self(),{store,Key,Value}},
{save_ok,RealRemaning};
<<_/binary>> ->
%% not enough streams
{not_enough_streams}
end;
%%get command
<<16#80:8,16#0:8,KeyLen:16/big,16#0:8,
DataType:8,Reserved:16/big,BodyLen:32/big,
Opaque:32/big,Cas:64/big,Key:KeyLen/big-binary-unit:8,
Remaining/binary>> ->
kvs ! {self(),{lookup,Key}},
receive
{lookup,Value} ->
{get_ok,Value,Remaining}
after 1000 ->
{get_timeout,Remaining}
end;
%% no match
<<_/binary>> ->
{not_engouh_streams}
end.
dict() ->
receive
{From,{store,Key,Value}} ->
put(Key,{ok,Value}),
dict();
{From,{lookup,Key}} ->
From ! {lookup,get(Key)},
dict()
end.
debug_print([H|T]) ->
io:format("~w,",[H]),
debug_print(T);
debug_print([])->
ok.
fill_all(C,0,L)->
L;
fill_all(C,N,L)->
N1=N-1,
L1=[C|L],
fill_all(C,N1,L1).
说明:
1. 16#80:8
16#代表16进制,80是memcached协议头的第一个字节 80代表request
具体协议内容memcached官网上有很详尽的解释
2. KeyLen:16/big
协议中key的长度是占2个字节 ,16是bit数 .
因为多于一个字节的数据在存储和传输时就会涉及字节序问题,
这里big代表的是大端/网络字节序,
因为我的测试client在传输数据前已经将数据转成网络字节序,所以这里接收必须是big
3. Key:KeyLen/big-binary-unit:8 ,
这里Key具体的字节数是由之前得到的KeyLen指定的,所以表示为Key:KeyLen,
因为这里的单位应该是字节,所以需要指定为unit:8,其实这里指定了binary
binary类型默认的unit就是8,即 实际的size = KeyLen * unit 个 bit
4. lookup没有找到指定key对应value时,这里没有按协议处理,以not_found为value返回给client,实际协议是返回一个status为非0的协议包
分享到:
相关推荐
erlang提供了binary_to_term 函数...这个函数都是c实现的,这里用erlang语言实现了,很有参考价值,其他语言可以参考这个解析erlang二进制协议数据。配套文章地址http://blog.csdn.net/mycwq/article/details/42460033
Erlang emulator 实现分析Erlang emulator 实现分析
Erlang Ranch是一个轻量级、高性能的网络协议栈,专为构建TCP服务器而设计。在游戏开发领域,由于其并发处理能力和强大的故障恢复机制,Erlang常被用来构建可扩展、高可用性的游戏服务器。Ranch库提供了一种简单的...
### Erlang Binary与Bit String 数据类型详解 #### 引言 Erlang 是一种功能强大且灵活的编程语言,尤其适合开发高并发、分布式及容错性应用。自 R12B 版本以来,Erlang 在处理二进制数据方面引入了两项重大更新:...
Erlang OTP 20.1 Windows 64-bit Binary File 下载地址:http://www.erlang.org/downloads
Erlang二进制协议Memcached客户端 外部文件 二进制协议规范 快速开始 您必须具有1.3或更高版本的memcached $> make $> make test $> sudo make install $> memcached -d 1> erlmc:start(). ok 2> erlmc:stats(). ...
下面我们将深入探讨如何使用Erlang实现这个功能,以及涉及的相关知识点。 首先,让我们看看`for_each_file.erl`可能的实现。在这个模块中,我们可能会定义一个名为`for_each_file/2`的函数,它接受两个参数:一个是...
这个项目是关于Megaco协议的实现,而“Erlang”是用于开发这个实现的编程语言。Erlang是一种功能强大的并行、分布式和容错的编程语言,特别适合于构建高可用性和实时性系统,如电信领域中的应用。 “erlang_erlang_...
标题中的“<27>erlang record”可能指的是Erlang编程语言中的Record特性,它是一种数据结构,类似于结构体或者哈希表,用于组织和操作数据。在Erlang中,Record提供了一种方便的方式来定义和访问具有固定字段的数据...
在给定的文件内容中,通过Erlang语言实现了KMP算法,以下是从文件内容中提取的关键知识点: 1. kmp_search/2函数:这是KMP算法的主函数,用于检查子串(SubString)是否存在于主串(String)中。该函数调用了kmp_...
此外,提供的"erlang的timer和实现机制.pdf"和"更多erlang资料下载.txt"也是进一步学习和研究的好资源。 总之,Erlang的timer模块是其强大并发能力的一个体现,通过熟练掌握这一部分,开发者可以构建出更加高效和...
Erlang的并发模型和 otp 设计模式使得系统能够轻松实现负载均衡和故障切换。当一个节点或进程失败时,系统可以重新分配工作,确保服务的连续性。 ### 9. BEAM虚拟机 BEAM是Erlang运行时系统的名称,全称为伯尔尼...
掌握这些基础知识后,你可以进一步学习如何在Erlang中编写RabbitMQ客户端,实现消息的发布和订阅,以及如何利用RabbitMQ实现可靠的数据传输和系统解耦。同时,了解Erlang的错误处理机制和调试工具,如observer和...
标题 "一种傻纸牌游戏的Erlang实现" 暗示了我们将探讨一个使用Erlang编程语言构建的简单纸牌游戏。Erlang是一种并发性极强、功能丰富的函数式编程语言,常用于构建分布式系统和高可用性的应用程序。 在描述中提到的...
### Erlang 实现遗传算法详解 #### 一、引言 遗传算法(Genetic Algorithm, GA)是一种模拟自然界中生物进化过程的优化搜索方法。它借鉴了自然选择、遗传、变异等生物进化的机制,通过迭代的方式寻找问题的最优解...
本文将深入探讨Erlang中的I/O协议,特别是它在STDLIB 1.17.4版本中的实现细节。 #### 标准库STDLIB简介 STDLIB是Erlang的一个核心模块,包含了各种通用的函数库,如列表操作、字符串处理、文件系统交互等。它为...
Erlang OTP是Erlang的官方实现,提供了完整的开发环境。 readers可以从Erlang官方网站下载最新的Windows binary版本。安装Erlang OTP非常简单,只需要按照安装程序的提示进行操作。 二、安装Emacs W32 Emacs W32是...
Erlang B和Erlang C是电信领域中两种重要的流量模型,用于预测和分析通信系统中的呼叫处理能力和拥塞情况。这两个模型由丹麦工程师Agner Krarup Erlang在20世纪初提出,至今仍广泛应用于现代通信网络的设计与优化。 ...