erlang behaviour小结之gen_s erver
首先清楚gen_s erver提供C/S架构中的服务端的实现,即定义了自己一套规范的服务器框架。
在以上基础上,具体学习下gen_s erver的实现过程。
先是定义模块的行为模式为gen_s erver
-module(lqg).
-behaviour(gen_**).
.
这里既然用了gen_s erver框架,那必须要实现gen_**的方法:gen_** callbacks
-export(). 外加模块的对外调用函数:API
-export().
-export().
接下来就是实现上面定义的函数:
start_link() ->
gen_**:start_link({local, lqg}, lqg, [], []). 对于start_link,
第一个参数为创建一个名为Name的**,现在的情况为在gen_srever将在本地被注册为lqg
第二个参数lqg, 则是回调模块的名字,也就是回调函数所放的那个模块。在这里,接口函数( start_link)和回调函数(init, handle_call 和 handle_cast)。一般来说这是好的编程实践,将代表同一个进程的代码包含在同一个模块中。
第三个参数[], 这个值将被原封不动传递给回调函数init。在这里,init无须任何输入数据将忽略这个参数.
第四个参数[],是参数的列表。
这里要注意的是:
1.gen_**:start_link 是同步的。只有等到gen_**被完全初始化并准备接受请求之后才会返回
2.如果gen_**是某棵**树的一部分,即gen_**是由一个督程启动的,那么必须使用
gen_**:start_link 。还有另外一个函数 gen_**:start 用于启动一个**的gen_**,即不是某棵**树一部分的一个gen_**
init(_Args) ->
{ok, channels()}.在注册名称成功后,新的gen_**进程会调用回调函数lqg:init([])
init返回{ok, State} ,其中State 是gen_**的内部状态。在这里,状态就是可用的频道channels。
alloc() ->
gen_**:call(lqg,alloc). 同步请求alloc() 用gen_**:call/2 实现.lqg 是gen_**的名字,必须和启动时的名字一样。alloc 是实际的请求
此时,请求以消息的形式发送给这个gen_**。当收到了请求之后,gen_**调用handle_call(Request,From, State) ,它应返回一个元组 {reply, Reply, State1}。Reply是需要回馈给客户端的答复,同时State1 是gen_**的状态的新值。
handle_call(_Request, _From, State) ->
{Ch, State2} = alloc(State),
{reply, Ch, State2}。 在这里,应答是分配了的频道Ch 然后gen_**将等待新的请求,并且现在保持了一个最新的可用频道的列表。
handle_cast({free,Ch},Chs) ->
Chs2 = free(Ch,Chs),
{noreply, Chs2}. 在这里,新的状态便是更新过的可用频道列表Chs2 。gen_**现在又可以接受新的请求了。
free(Ch) ->
gen_**:cast(lqg,{free,Ch}).异步请求free(ch) 使用 gen_**:cast/2 实现
lqg 是gen_**的名称。{free, Ch} 是实际的请求。
请求被装在一个消息中发给gen_**的cast ,这调用了 free ,然后返回了 ok 。当gen_**收到请求之后,它会调用handle_cast(Request, Stats) ,会返回一个元组{noreply, State1} 。 State1 是gen_**状态的新值。
handle_info(_Info, State) ->
{noreply, State}. 用来处理请求之外的信息。
terminate(_Reason, _State) ->
ok. 终止函数,终止正在运行的进程
若gen_**是某个**树的一部分,则无需停止函数。它的督程会自动终止它;
如果gen_**并非某个**树的一部分,那么可以用一个停止函数;
如果在终止之前需要进行一些清理工作,那么关闭策略必须是一个超时值,同时gen_**必须在init 函数中设置为捕获退出信号。当gen_**被要求关闭时,它就会调用回调函数terminate(shutdown, State)。
code_change(_OldVsn, State, _Extra) ->
{ok, State}.正如其名,此函数用来进行代码版本替换。是**热部署或代码升级时做callback修改进程状态
_OldVsn:旧版本 State:gen_**的内部状态 _Extra:原封不动的传递过来的更新指令
如果更新成功,返回{ok,State2},如果失败返回{error,Reason},并回**到旧版本。
在以上基础上,具体学习下gen_s erver的实现过程。
先是定义模块的行为模式为gen_s erver
-module(lqg).
-behaviour(gen_**).
.
这里既然用了gen_s erver框架,那必须要实现gen_**的方法:gen_** callbacks
-export(). 外加模块的对外调用函数:API
-export().
-export().
接下来就是实现上面定义的函数:
start_link() ->
gen_**:start_link({local, lqg}, lqg, [], []). 对于start_link,
第一个参数为创建一个名为Name的**,现在的情况为在gen_srever将在本地被注册为lqg
第二个参数lqg, 则是回调模块的名字,也就是回调函数所放的那个模块。在这里,接口函数( start_link)和回调函数(init, handle_call 和 handle_cast)。一般来说这是好的编程实践,将代表同一个进程的代码包含在同一个模块中。
第三个参数[], 这个值将被原封不动传递给回调函数init。在这里,init无须任何输入数据将忽略这个参数.
第四个参数[],是参数的列表。
这里要注意的是:
1.gen_**:start_link 是同步的。只有等到gen_**被完全初始化并准备接受请求之后才会返回
2.如果gen_**是某棵**树的一部分,即gen_**是由一个督程启动的,那么必须使用
gen_**:start_link 。还有另外一个函数 gen_**:start 用于启动一个**的gen_**,即不是某棵**树一部分的一个gen_**
init(_Args) ->
{ok, channels()}.在注册名称成功后,新的gen_**进程会调用回调函数lqg:init([])
init返回{ok, State} ,其中State 是gen_**的内部状态。在这里,状态就是可用的频道channels。
alloc() ->
gen_**:call(lqg,alloc). 同步请求alloc() 用gen_**:call/2 实现.lqg 是gen_**的名字,必须和启动时的名字一样。alloc 是实际的请求
此时,请求以消息的形式发送给这个gen_**。当收到了请求之后,gen_**调用handle_call(Request,From, State) ,它应返回一个元组 {reply, Reply, State1}。Reply是需要回馈给客户端的答复,同时State1 是gen_**的状态的新值。
handle_call(_Request, _From, State) ->
{Ch, State2} = alloc(State),
{reply, Ch, State2}。 在这里,应答是分配了的频道Ch 然后gen_**将等待新的请求,并且现在保持了一个最新的可用频道的列表。
handle_cast({free,Ch},Chs) ->
Chs2 = free(Ch,Chs),
{noreply, Chs2}. 在这里,新的状态便是更新过的可用频道列表Chs2 。gen_**现在又可以接受新的请求了。
free(Ch) ->
gen_**:cast(lqg,{free,Ch}).异步请求free(ch) 使用 gen_**:cast/2 实现
lqg 是gen_**的名称。{free, Ch} 是实际的请求。
请求被装在一个消息中发给gen_**的cast ,这调用了 free ,然后返回了 ok 。当gen_**收到请求之后,它会调用handle_cast(Request, Stats) ,会返回一个元组{noreply, State1} 。 State1 是gen_**状态的新值。
handle_info(_Info, State) ->
{noreply, State}. 用来处理请求之外的信息。
terminate(_Reason, _State) ->
ok. 终止函数,终止正在运行的进程
若gen_**是某个**树的一部分,则无需停止函数。它的督程会自动终止它;
如果gen_**并非某个**树的一部分,那么可以用一个停止函数;
如果在终止之前需要进行一些清理工作,那么关闭策略必须是一个超时值,同时gen_**必须在init 函数中设置为捕获退出信号。当gen_**被要求关闭时,它就会调用回调函数terminate(shutdown, State)。
code_change(_OldVsn, State, _Extra) ->
{ok, State}.正如其名,此函数用来进行代码版本替换。是**热部署或代码升级时做callback修改进程状态
_OldVsn:旧版本 State:gen_**的内部状态 _Extra:原封不动的传递过来的更新指令
如果更新成功,返回{ok,State2},如果失败返回{error,Reason},并回**到旧版本。
没有找到相关结果
已邀请:
0 个回复