首页 > 代码库 > [Erlang之旅 0004] gen_server
[Erlang之旅 0004] gen_server
gen_server:start_link(ServerName, Module, Args, Options) -> Result
ServerName={local, Name}|{global, GlobalName}|{via, Module, ViaName}
Option = {debug, Dbgs}|{timeout, Time}|{spawn ——opt, Sopts}
Module: 回调模块的名称
Args: 传给回调模块中init函数的参数
call(ServerRef, Request) -> Reply %%handle_call之间的交互, 实现远程调用
abcast(Name, Request) -> abcast
muti_call(Name, Request) -> Result
gen_server 和回调模块中的回调函数对应关系
gen_server module Callback module
-------------------------- -----------------------
gen_server:start_link --------> Module:init/1
gen_server:call
gen_server:multi_call ---------> Module:handle_call/3 %% 函数的同步调用
gen_server:cast
gen_server:abcast ----------> Module:handle_cast/2 %% 函数的异步调用
- ----------> Module:handle_info/2 %% 处理发给服务器的原生消息,handle_call /handle_cast不处理的消息
- ----------> Module:terminate/2 %% 服务器终止,可以对State 的数据进行处理
- ----------> Module:code_change/3 %% 对于代码的升级和替换
以代码说明其使用
1 -module(tcp_socket2). 2 -behaviour(gen_server). 3 4 -export([start/0, stop/0, login/1]). 5 6 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). 7 8 start() -> 9 io:format("[~p] start()~n", [calendar:now_to_local_time(erlang:now())]), 10 gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). 11 12 13 stop() -> 14 io:format("[~p] stop() ~n", [calendar:now_to_local_time(erlang:now())]), 15 gen_server:call(?MODULE, stop). 16 17 18 login(Who) -> 19 io:format("[~p] login(~p) ~n", [calendar:now_to_local_time(erlang:now()), Who]), 20 gen_server:call(?MODULE, {login, Who}). 21 22 init([]) -> 23 io:format("[~p] init() ~n", [calendar:now_to_local_time(erlang:now())]), 24 {ok, ets:new(?MODULE, [])}. 25 26 handle_call({login, Who}, _From, Tab) -> 27 io:format("[~p] handle_call({login, ~p})", [calendar:now_to_local_time(erlang:now()), Who]), 28 Reply = case ets:lookup(Tab, Who) of 29 [] -> ets:insert(Tab, {Who,0}), 30 {welcome, Who} 31 end, 32 {reply, Reply, Tab}; 33 handle_call(stop, _From, Tab) -> 34 {stop, normal, stopped, Tab}. 35 handle_cast(_Msg, State) -> {noreply, State}. 36 handle_info(_Info, State) -> {noreply, State}. 37 terminate(_Reason, _State) -> 38 ok. 39 code_change(_OldVsn, State, Extra) -> {ok, State}.
在一个终端显示的信息,可以观察其启动函数的顺序 start -> init login -> handle_call
1> c(tcp_socket2).
tcp_socket2.erl:39: Warning: variable ‘Extra‘ is unused
{ok,tcp_socket2}
2> tcp_socket2:start().
[{{2014,7,15},{14,34,21}}] start()
[{{2014,7,15},{14,34,21}}] init()
{ok,<0.40.0>}
3> tcp_socket2:login("nike").
[{{2014,7,15},{14,34,45}}] login("nike")
[{{2014,7,15},{14,34,45}}] handle_call({login, "nike"}){welcome,"nike"}
4> tcp_socket2:stop().
[{{2014,7,15},{14,45,26}}] stop()
stopped
5>