您的位置:首页 > 其它

Erlang — gen_server

2015-06-02 10:55 417 查看
热代码交换:如果要修改一个服务器的行为,不用停止它,只需要发送一个包含新代码的消息,它就会提取新代码,然后用新代码和老代码

            的回话数据继续工作。

编写gen_server回调模块的简要步骤:

   

   1、确定回调模块名。

   2、编写接口函数。

   3、在回调模块里编写六个必需的回调函数。

  在回调模块中必须导出六个回调方法:init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3

   简单的回调模板:

    

   -module(gen_server_template).

   -behaviour(gen_server).

   %% ====================================================================

   %% gen_server 回调行数

   %% ====================================================================

   -export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).

   -record(state,{}).

   init([]) ->

        {ok,#state{}}.

   handle_call(_Request,_From,State) ->
Replay = ok,
{replay,Replay,State}.

   handle_cast(_Msg,State) ->
{noreplay,State}.

   handle_info(_Info,State) ->
{ok,State}.

  terminate(_Reason,_State) ->
ok.

  code_change(_OldVsn,State,_Extra) ->
{ok,State}.

 对于通用服务器而言,用户主要完成以下两件事:

  

   1、启动服务器进程

   2、向进程发消息(并获取应答)

 gen_server提供了三个主要的库函数来实现这些基本功能:

  

  ---------------------------------------------------------------------------------------------------------------------------------------

     库函数                         对应回调函数                          描述

  ---------------------------------------------------------------------------------------------------------------------------------------

    gen_server:start_link/4         Module:init/1              
启动并链接一个gen_server容器进程

    gen_server:call/2               Module:handle_call/3        向gen_server进程发送同步消息并等待应答

    gen_server:case/2               Module:handle_cast/2        向gen_server进程发送异步消息

  ----------------------------------------------------------------------------------------------------------------------------------------

 注:gen_server:call/2 函数实现了可靠的同步请求—响应功能,其中默认应答等待超时为5秒,一旦超时便放弃等待应答,

   

     gen_server:call/3 允许以毫秒为单位设置超时,同时也可以通过将超时时间设置为infinity来禁用超时。

     handle_info/2 没有对应的gen_server库函数,这个回调是一个重要的特例,所有未经过call或cast库函数发送至gen_server

  

     信箱的消息都由它处理(通常是直接用!运算符发送的裸消息)。

  gen_server:start_link({local,?SERVER}?MODULE,[port],[]).执行这个调用的时候,会派生出一个新的gen_server容器

   

  进程,新进程将以SERVER宏展开后对于的名称在本地节点上注册,然后等待行为模式实现模块中的init/1回调函数完成进程

  

  初始化,最后返回。

  example:

%%% @author xiaomage

%%% @doc 模拟银行开户、存款、取款操作

%%% @todo Add description to my_banck.

-module(my_banck).

-behaviour(gen_server).

-define(SERVER,?MODULE).

%%-------------------------------

%% gen_server call_back function

%%-------------------------------

-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).

%%-------------------------------

%% API function

%%-------------------------------

-export([start/0,stop/0,new_account/1,deposit/2,withdraw/2]).

start() ->
gen_server:start_link({local,?SERVER}, ?MODULE, [], []).

stop() ->
gen_server:call(?MODULE, stop).

new_account(Who) ->
gen_server:call(?MODULE, {new,Who}).

deposit(Who,Amount) ->
gen_server:call(?MODULE, {add,Who,Amount}).

withdraw(Who,Amount) ->
gen_server:call(?MODULE, {remove,Who,Amount}).

init([]) ->
{ok,ets:new(?MODULE, [])}.

handle_call({new,Who},_From,Tab) ->
Reply = case ets:lookup(Tab, Who) of
[] -> 
ets:insert(Tab, {Who,0}),
{welcome,Who};
[_] ->
{Who,you_are_already_a_customer}
end,
{reply,Reply,Tab};

handle_call({add,Who,X},_From,Tab) ->
Reply = case ets:lookup(Tab, Who) of
[] ->
not_a_customer;
[{Who,Amount}] ->
NewAmount = Amount + X,
ets:insert(Tab, {Who,NewAmount}),
{thanks,Who,you_banck_is ,NewAmount}

             end,

    {reply,Reply,Tab};

handle_call({remove,Who,X},_From,Tab) ->
Reply = case ets:lookup(Tab, Who) of
[] ->
not_a_customer;
[{Who,Amount}] when Amount >= X ->
NewAmount = Amount - X,
ets:insert(Tab, {Who,NewAmount}),
{thanks,Who,you_banck_is,NewAmount};
[{Who,Amount}] ->
{sorry,Who,you_only_hava,Amount,in_the_banck}
end,
{reply,Reply,Tab};

handle_call({stop}, _From, Tab) ->
{stop,normal,stopped,Tab}.

handle_cast(_Msg,State) ->
{noreply,State}.

handle_info(_Info,State) ->
{ok,State}.

terminate(_Reason,_State) ->
ok.

code_change(_OldVsn,State,_Extra) ->
{ok,State}.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: