[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>

[Erlang之旅 0004] gen_server

时间: 2024-12-28 02:00:30

[Erlang之旅 0004] gen_server的相关文章

[Erlang之旅 0009] socket 通讯

前面学习完了gen_server .gen_tcp 现在做一个简易的socket通讯,服务端将接收到的信息返回给客户端,具体代码如下: 服务端: 1 -module(tcp_socket3). 2 -behaviour(gen_server). 3 4 -export([start/0, login/2, stop/0]). 5 -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_chan

Erlang generic standard behaviours -- gen_server system msg

这是Erlang generic standard behaviors gen_server 分析的系列的最后一篇,主要分析gen_server module 辅助性的功能函数. 在gen_server 的MAIN loop 流程中,除了处理Parent 的'EXIT' 消息, user module 常规消息之外, 还处理了一类 system 消息. 这一类system 消息的来源是一个sys 的module,在Erlang OTP体系中,sys module 主要有两大类的作用,一个是热更,

[Erlang之旅 0005] ETS 和Record

ETS 提供“键-值” 搜索表, 驻留在内存中,速度较快.是缓存的大利器. record 作为erlang的一种数据结构,通常用于函数量传递. ETS中创建表, 对数据进行增.删.改.查 , 及关闭表常用的函数 ets:new(Name, Options) -> tid()   %% 创建表 Options: Type: set | ordered_set | bag | duplicate_bag set: 每一个元组的键值都不能相同:ordered_set:元组键不能相同,并且会进行排序 b

[Erlang之旅 0008] string 常用函数

参考文档:http://www.erlang.org/erldoc?q=string%3Bright&x=-967&y=-384 string类型,经常用到,所有练习一下: 3> string:len("fan"). %% 字符串长度 3 4> string:len("你的"). 2 5> string:len("fan你的中国"). 7 6> string:equal("an",&qu

[Erlang之旅 0006] 二进制位串

位串可以写作<< E1,E2....En>>,其中双小于号和双大于号之间可以包含零个或多个区段指示符,位串以比特位为单位的整体长度.区段指示符可以为以下形式之一: Data | Data:Size | Data/TypeSpecifiers | Data:Size/TypeSpecifiers TypeSpecifiers :  主要控制区段编解码的细节,它由一个或多个由(-)分隔的原子组成,例如 integer-unsigned-big 原子出现的顺序不重要,可以用的指示符如下,

[Erlang之旅 0001] 基本数据类型

数据的基本类型:数值.原子.元组.列表 1 .在Erlang的世界内,一但变量赋值之后,变量不会改变,如果再赋予其它值,就会报错,这和其它大多数语言不同.变量命名通常以大写字母开头,如果有多个单词,则每个单词的首字母大写,如:LastName='YY' 2 . 数值:包含整数和浮点 大部分的算术运算都会自动进行类型转换. 3. 原子 原子是一种仅由字符序列来标识的特殊字符串常量.两个原子只要具有相同的字符表示,就完全相同. 原子的命名: 原子通常以小写字母开头,首字母后可以用大写字母.数字.下划

erlang中启动一个gen_server和一个纯粹进程的区别

1.在genserver的启动过程中,内部调用的是proc_lib:start_link(M,F,A,Time,SpawnOpts),当该函数被调用的时候,启动gen_server的进程必须wait,直到gen_server进程在执行init_it函数时,调用proc_lib:init_ack将gen_server的进程号返回给启动进程,至此一个gen_server进程才启动完成: 2.对于一个单纯的erlang进程来说,调用spawn函数来启动他,会立刻返回.

Erlang generic standard behaviours -- gen_server noblock call

在Erlang 系统中,经常需要gen_server 进程来处理共享性的数据,也就是总希望一个gen_server 进程来为多个普通进程提供某种通用性的服务,这也是gen_server 设计的初衷.但是,由于公平调度的原因,在Erlang体系中,每个process 能获得的资源都是同等的:同等的CPU时间片(还有默认情况下同等的初始化内存). 也就是gen_server 进程只能获得1/(N+1)的CPU时间片,为N个进程提供通用性的服务,而无法违背公平调度的原则使gen_server 进程获得

Erlang generic standard behaviours -- gen_server terminate

gen_server 主体 module 已经分析完了(http://www.cnblogs.com/--00/p/4271982.html),接着,分析下gen_server 中的terminate .首先分析一个问题, 这个问题是之前在weibo 上和别人讨论过的一个问题: Why will a rpc:call started gen_server process terminate with normal reason? 注:被call 的gen_server 进程 trap_exit