`
bachmozart
  • 浏览: 111666 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

erlang轻松实现memcached binary协议

阅读更多
简单实现了下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的协议包





分享到:
评论
2 楼 bachmozart 2009-06-04  
willko 写道
大牛啊,,,

erlang的语法好怪,,以后一定要学学```


大牛是yufeng,litaocheng他们,我也准备基础好点了,再去骚扰他们,呵呵
1 楼 willko 2009-06-04  
大牛啊,,,

erlang的语法好怪,,以后一定要学学```

相关推荐

    erlang语言实现binary_to_term完整代码

    erlang提供了binary_to_term 函数...这个函数都是c实现的,这里用erlang语言实现了,很有参考价值,其他语言可以参考这个解析erlang二进制协议数据。配套文章地址http://blog.csdn.net/mycwq/article/details/42460033

    Erlang emulator 实现分析

    Erlang emulator 实现分析Erlang emulator 实现分析

    erlang ranch实现的游戏tcp服务器

    Erlang Ranch是一个轻量级、高性能的网络协议栈,专为构建TCP服务器而设计。在游戏开发领域,由于其并发处理能力和强大的故障恢复机制,Erlang常被用来构建可扩展、高可用性的游戏服务器。Ranch库提供了一种简单的...

    介绍 Erlang binary 和 bit string 数据类型的经典文章

    ### Erlang Binary与Bit String 数据类型详解 #### 引言 Erlang 是一种功能强大且灵活的编程语言,尤其适合开发高并发、分布式及容错性应用。自 R12B 版本以来,Erlang 在处理二进制数据方面引入了两项重大更新:...

    Erlang OTP 20.1 Windows 64-bit Binary File

    Erlang OTP 20.1 Windows 64-bit Binary File 下载地址:http://www.erlang.org/downloads

    erlmc:Erlang Memcached二进制协议客户端

    Erlang二进制协议Memcached客户端 外部文件 二进制协议规范 快速开始 您必须具有1.3或更高版本的memcached $&gt; make $&gt; make test $&gt; sudo make install $&gt; memcached -d 1&gt; erlmc:start(). ok 2&gt; erlmc:stats(). ...

    for_each_file 用erlang代码实现遍历文件

    下面我们将深入探讨如何使用Erlang实现这个功能,以及涉及的相关知识点。 首先,让我们看看`for_each_file.erl`可能的实现。在这个模块中,我们可能会定义一个名为`for_each_file/2`的函数,它接受两个参数:一个是...

    megaco_session-0.5.rar_erlang_erlang Megaco_megaco

    这个项目是关于Megaco协议的实现,而“Erlang”是用于开发这个实现的编程语言。Erlang是一种功能强大的并行、分布式和容错的编程语言,特别适合于构建高可用性和实时性系统,如电信领域中的应用。 “erlang_erlang_...

    <27>erlang record

    标题中的“&lt;27&gt;erlang record”可能指的是Erlang编程语言中的Record特性,它是一种数据结构,类似于结构体或者哈希表,用于组织和操作数据。在Erlang中,Record提供了一种方便的方式来定义和访问具有固定字段的数据...

    KMP(Erlang)代码实现

    在给定的文件内容中,通过Erlang语言实现了KMP算法,以下是从文件内容中提取的关键知识点: 1. kmp_search/2函数:这是KMP算法的主函数,用于检查子串(SubString)是否存在于主串(String)中。该函数调用了kmp_...

    erlang的timer和实现机制

    此外,提供的"erlang的timer和实现机制.pdf"和"更多erlang资料下载.txt"也是进一步学习和研究的好资源。 总之,Erlang的timer模块是其强大并发能力的一个体现,通过熟练掌握这一部分,开发者可以构建出更加高效和...

    erlang编程 Introducing Erlang

    Erlang的并发模型和 otp 设计模式使得系统能够轻松实现负载均衡和故障切换。当一个节点或进程失败时,系统可以重新分配工作,确保服务的连续性。 ### 9. BEAM虚拟机 BEAM是Erlang运行时系统的名称,全称为伯尔尼...

    erlang_win64.rar

    掌握这些基础知识后,你可以进一步学习如何在Erlang中编写RabbitMQ客户端,实现消息的发布和订阅,以及如何利用RabbitMQ实现可靠的数据传输和系统解耦。同时,了解Erlang的错误处理机制和调试工具,如observer和...

    一种傻纸牌游戏的Erlang实现

    标题 "一种傻纸牌游戏的Erlang实现" 暗示了我们将探讨一个使用Erlang编程语言构建的简单纸牌游戏。Erlang是一种并发性极强、功能丰富的函数式编程语言,常用于构建分布式系统和高可用性的应用程序。 在描述中提到的...

    Erlang实现遗传算法.docx

    ### Erlang 实现遗传算法详解 #### 一、引言 遗传算法(Genetic Algorithm, GA)是一种模拟自然界中生物进化过程的优化搜索方法。它借鉴了自然选择、遗传、变异等生物进化的机制,通过迭代的方式寻找问题的最优解...

    erlang最新api

    本文将深入探讨Erlang中的I/O协议,特别是它在STDLIB 1.17.4版本中的实现细节。 #### 标准库STDLIB简介 STDLIB是Erlang的一个核心模块,包含了各种通用的函数库,如列表操作、字符串处理、文件系统交互等。它为...

    Erlang开发环境搭建

    Erlang OTP是Erlang的官方实现,提供了完整的开发环境。 readers可以从Erlang官方网站下载最新的Windows binary版本。安装Erlang OTP非常简单,只需要按照安装程序的提示进行操作。 二、安装Emacs W32 Emacs W32是...

    ErlangB和ErlangC计算工具(exe可执行文件+excel两个)

    Erlang B和Erlang C是电信领域中两种重要的流量模型,用于预测和分析通信系统中的呼叫处理能力和拥塞情况。这两个模型由丹麦工程师Agner Krarup Erlang在20世纪初提出,至今仍广泛应用于现代通信网络的设计与优化。 ...

Global site tag (gtag.js) - Google Analytics