Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5119551
  • 博文数量: 921
  • 博客积分: 16037
  • 博客等级: 上将
  • 技术积分: 8469
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-05 02:08
文章分类

全部博文(921)

文章存档

2020年(1)

2019年(3)

2018年(3)

2017年(6)

2016年(47)

2015年(72)

2014年(25)

2013年(72)

2012年(125)

2011年(182)

2010年(42)

2009年(14)

2008年(85)

2007年(89)

2006年(155)

分类: Python/Ruby

2012-07-03 22:38:38

1. 首先我们来看例子1。


  1. -module(ch1).
  2. -export([start/0]).
  3. -export([alloc/0, free/1]).
  4. -export([init/0]).

  5. %% 启动频道服务
  6. start() ->
  7.     spawn(ch1, init, []). %% 创建一个进程,这个进程会调用init方法,参数为[]
  8. %% 获取一个空闲的频道
  9. alloc() ->
  10.     ch1 ! {self(), alloc},
  11.     receive
  12.         {ch1, Res} ->
  13.             Res
  14.     end.
  15. %% 释放一个频道
  16. free(Ch) ->
  17.     ch1 ! {free, Ch},
  18.     ok.
  19. %% 初始化频道信息
  20. init() ->
  21.     register(ch1, self()), %% 注册名称为ch1的进程
  22.     Chs = channels(), %% 调用channels方法获取 {_Allocated = [], _Free = [1,2,3,4,5,...,100]}. _Allocated 列表表示已经占用的频道,_Free 列表表示空闲的频道
  23.     loop(Chs).
  24. loop(Chs) ->
  25.     receive
  26.         {From, alloc} -> %% 接受到一个获取频道消息
  27.             {Ch, Chs2} = alloc(Chs), %% 调用alloc/1方法,获取一个未被占用的频道
  28.             From ! {ch1, Ch}, %% 发送一个消息到调用者
  29.             loop(Chs2); %% 继续等待消息
  30.         {free, Ch} -> %% 接受到一个释放频道Ch的消息
  31.             Chs2 = free(Ch, Chs), %% 调用free/2,将该频道放入空闲频道列表中
  32.             loop(Chs2) %% 继续等待消息
  33.     end.
  34. %% 初始化已占用频道列表和空闲频道列表
  35. channels() ->
  36.    {_Allocated = [], _Free = lists:seq(1,100)}.

  37. %% 获取一个空闲频道,并放入已占用频道列表中
  38. alloc({Allocated, [H|T] = _Free}) ->
  39.    {H, {[H|Allocated], T}}.

  40. %% 将频道Ch从已占用频道列表中移除,放入空闲列表中
  41. free(Ch, {Alloc, Free} = Channels) ->
  42.    case lists:member(Ch, Alloc) of
  43.       true ->
  44.          {lists:delete(Ch, Alloc), [Ch|Free]};
  45.       false ->
  46.          Channels
  47.    end.

上面那个例子中,主要实现的是 频道服务 功能。用户通过 alloc/0 方法获取一个空闲频道, 通过free/1 去释放一个频道。我已经添加了比较详细的注释

2. 接下来,我们再看一个例子


  1. -module(server).
  2. -export([start/1]).
  3. -export([call/2, cast/2]).
  4. -export([init/1]).
  5. start(Mod) ->
  6.     spawn(server, init, [Mod]).
  7. call(Name, Req) ->
  8.     Name ! {call, self(), Req},
  9.     receive
  10.         {Name, Res} ->
  11.             Res
  12.     end.
  13. cast(Name, Req) ->
  14.     Name ! {cast, Req},
  15.     ok.
  16. init(Mod) ->
  17.     register(Mod, self()),
  18.     State = Mod:init(),
  19.     loop(Mod, State).
  20. loop(Mod, State) ->
  21.     receive
  22.         {call, From, Req} ->
  23.             {Res, State2} = Mod:handle_call(Req, State),
  24.             From ! {Mod, Res},
  25.             loop(Mod, State2);
  26.         {cast, Req} ->
  27.             State2 = Mod:handle_cast(Req, State),
  28.             loop(Mod, State2)
  29.     end.


  1. -module(ch2).
  2. -export([start/0]).
  3. -export([alloc/0, free/1]).
  4. -export([init/0, handle_call/2, handle_cast/2]).

  5. %% 启动服务
  6. start() ->
  7.     server:start(ch2).

  8. %% 功能定制 获取空闲频道
  9. alloc() ->
  10.     server:call(ch2, alloc).

  11. %% 功能定制 释放频道
  12. free(Ch) ->
  13.     server:cast(ch2, {free, Ch}).

  14. init() ->
  15.     channels().

  16. %% 获取频道的回调函数
  17. handle_call(alloc, Chs) ->
  18.     alloc(Chs). % => {Ch,Chs2}
  19. %% 释放频道的回调函数
  20. handle_cast({free, Ch}, Chs) ->
  21.     free(Ch, Chs). % => Chs2

  22. channels() ->
  23.    {_Allocated = [], _Free = lists:seq(1,100)}.

  24. alloc({Allocated, [H|T] = _Free}) ->
  25.    {H, {[H|Allocated], T}}.

  26. free(Ch, {Alloc, Free} = Channels) ->
  27.    case lists:member(Ch, Alloc) of
  28.       true ->
  29.          {lists:delete(Ch, Alloc), [Ch|Free]};
  30.       false ->
  31.          Channels
  32.    end.

我们将例子1中 能够通用的 代码剥离,所谓能够通用就是,如果我们要实现另一个服务器模型,也可以使用 server 服务器来实现。

另一个好处就是,例子1 中,如果你要添加一个消息类型,则需要修改服务器loop函数,而 例子2中,只需要修改定制部分的功能,和新增回调函数就能实现,

那么这样就能保证服务器的通用,稳定。

模块 server 对应的是极大简化了的Erlang/OTP中的 gen_server 行为。

标准 Erlang/OTP 行为有:

gen_server用于实现 C/S 结构中的服务端。gen_fsm用于实现有限状态机。gen_event用于实现事件处理功能。supervisor用于实现监督树中的督程。


from:

http://www.cnblogs.com/yourihua/archive/2012/05/12/2497702.html


阅读(1755) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~