好记性,不如烂鼻头!!
说明我们的事例都是来自《erlang程序设计》第16节,但是会做我自己调整,以使其更接近OTP的标准gen_server模版本省。
本例分成三大部分,第一部分 是对《erlang程序设计中的代码》中简单例子进行说明;第二部分是关注如何更快速地编写一个gen_server服务;第三部分是gen_server标准实现源代码分析,看看我们还需要补充什么!!
现在就开始了!
ex1: server1
-module(server1).
-export([start/2,rpc/2]).
%%启动一个空的等待进程
start(Name, Mod) ->
register(Name, spawn(fun() -> loop(Name,Mod, Mod:init())end)).
%远程调用接口
rpc(Name,Request) ->
Name ! {self(),Request},
receive
{Name, Response} ->
Response
end.
loop(Name,Mod,State)->
receive
{From,Request}->
%%回到具体的函数处理模块
%%并返回 结果集 和 状态值
{Response , State1} = Mod:handle_call(Request,State),
%%返回到到rpc的值
From ! {Name, Response},
%% 采用尾递归技术来循环
loop(Name,Mod,State1)
end.
-module(name_server1).
%%给server1回到函数
-export([init/0,handle_call/2]).
-export([add/2,whereis/1]).
start()->server1:start(name_server,name_server1).
init()->dict:new().
handle_call({add,Name,Place},Dict) -> {ok,dict:store(Name,Place,Dict)};
handle_call({whereis,Name},Dict) ->{dict:find(Name,Dict),Dict}.
add(Name,Place) -> server1:rpc(name_server,{add,Name,Place}).
whereis(Name) -> server1:rpc(name_server,{whereis,Name}).
ex2:server2 加入异常处理机制
-module(server2).
-export([start/2,rpc/2]).
start(Name, Mod) ->
register(Name, spawn(fun() -> loop(Name,Mod, Mod:init())end)).
rpc(Name,Request) ->
Name ! {self(),Request},
receive
{Name,crash} -> exit(rpc);
{Name, ok, Response} -> Response
end.
loop(Name,Mod,OldState)->
receive
{From,Request}->
try Mod:handle_call(Request,OldState) of
{Response, NewState} ->
From ! {Name,Response},
loop(Name,Mod,NewState)
%% 加入了异常处理机制 当出现则回调 terminate函数 请求
catch
_:Why ->
From ! {Name, crash},
Mod:terminate(Why, OldState)
end
end.
-module(name_server2).
%%给server1回到函数
%%增加 中止的回调函数
-export([init/0,handle_call/2, terminate/2 ]).
-export([add/2,whereis/1]).
start()->server2:start(name_server, name_server2).
init()->dict:new().
%%当发生中止时 回调函数
terminate(Reason, State)->
io:format("server caused exception ~p state ~p ~n",[Reason,State]).
handle_call({add,Name,Place},Dict) -> {ok,dict:store(Name,Place,Dict)};
handle_call({whereis,Name},Dict) ->{dict:find(Name,Dict),Dict}.
add(Name,Place) -> server2:rpc(name_server,{add,Name,Place}).
whereis(Name) -> server2:rpc(name_server,{whereis,Name}).
ex3: server3 加入热代码备份
%% ---
%% Excerpted from "Programming Erlang",
%% published by The Pragmatic Bookshelf.
%% Copyrights apply to this code. It may not be used to create training material,
%% courses, books, articles, and the like. Contact us if you are in doubt.
%% We make no guarantees that this code is fit for any purpose.
%% Visit http://www.pragmaticprogrammer.com/titles/jaerlang for more book information.
%%---
-module(server3).
-export([start/2, rpc/2, swap_code/2]).
start(Name, Mod) ->
register(Name,
spawn(fun() -> loop(Name,Mod,Mod:init()) end)).
rpc(Name, Request) ->
Name ! {self(), Request},
receive
{Name, Response} -> Response
end.
loop(Name, Mod, OldState) ->
receive
{From, {swap_code, NewCallBackMod}} ->
%% 发送 确认信息到对应的字段
From ! {Name, ack},
%% 开启新的代码处理流程循环
loop(Name, NewCallBackMod, OldState);
{From, Request} ->
{Response, NewState} = Mod:handle_call(Request, OldState),
From ! {Name, Response},
loop(Name, Mod, NewState)
end.
-module(name_server2).
%%给server1回到函数
%%增加 中止的回调函数
-export([init/0,handle_call/2, terminate/2 ]).
-export([add/2,whereis/1]).
start()->server3:start(name_server, name_server2).
init()->dict:new().
%%当发生中止时 回调函数
terminate(Reason, State)->
io:format("server caused exception ~p state ~p ~n",[Reason, State]).
handle_call({add,Name,Place},Dict) -> {ok,dict:store(Name,Place,Dict)};
handle_call({whereis,Name},Dict) ->{dict:find(Name,Dict),Dict}.
add(Name,Place) -> server3:rpc(name_server,{add,Name,Place}).
whereis(Name) -> server3:rpc(name_server,{whereis,Name}).
%% 增加热代码替换工作
swap_code(Name, Mod) -> server3:rpc(Name, {swap_code, Mod}).
ex4 综合并加入 状态控制
%% ---
%% Excerpted from "Programming Erlang",
%% published by The Pragmatic Bookshelf.
%% Copyrights apply to this code. It may not be used to create training material,
%% courses, books, articles, and the like. Contact us if you are in doubt.
%% We make no guarantees that this code is fit for any purpose.
%% Visit http://www.pragmaticprogrammer.com/titles/jaerlang for more book information.
%%---
-module(server4).
-export([start/2, call/2, swap_code/2]).
start(Name, Mod) ->
register(Name, spawn(fun() -> loop(Name,Mod,Mod:init()) end)).
swap_code(Name, Mod) -> call(Name, {swap_code, Mod}).
call(Name, Request) ->
Name ! {self(), Request},
receive
{Name, crash} -> exit(rpc);
{Name, ok, Response} -> Response
end.
%% 加入状态判读
loop(Name, Mod, OldState) ->
receive
{From, {swap_code, NewCallbackMod}} ->
case Mod:code_change(OldState) of
{ok, _State}->
From ! {Name, ok, ack},
loop(Name, NewCallbackMod, OldState);
{stop, _state}->
From ! {Name, crash}
end;
{From, Request} ->
try Mod:handle_call(Request, OldState) of
{reply, Response, NewState} ->
From ! {Name, ok, Response},
loop(Name, Mod, NewState);
{noreply, NewState} ->
loop(Name, Mod, NewState)
catch
_: Why ->
From ! {Name, crash},
Mod:terminate(Why, OldState)
end
end.
-module(name_server4).
%%给server1回到函数
%%增加 中止的回调函数
-export([init/0,handle_call/2, code_change/1, terminate/2 ]).
-export([add/2,whereis/1]).
start()->server3:start(name_server, name_server4).
init()->dict:new().
code_change(_State)->
{ok}.
%%当发生中止时 回调函数
terminate(Reason, State)->
io:format("server caused exception ~p state ~p ~n",[Reason, State]).
handle_call({add,Name,Place},Dict) -> {reply,ok,dict:store(Name,Place,Dict)};
handle_call({whereis,Name},Dict) ->{reply,dict:find(Name,Dict),Dict}.
add(Name,Place) -> server4:rpc(name_server,{add,Name,Place}).
whereis(Name) -> server4:rpc(name_server,{whereis,Name}).
%% 增加热代码替换工作
swap_code(Name, Mod) -> server4:rpc(ok, Name, {swap_code, Mod}).
分享到:
相关推荐
erlang_otp_win64_25.0
是erlang_otp_20.3 的win64安装包,内为exe文件,一路next即可安装完成 是适用于多线程、分布式开发的语言,也是如rabbitmq等重要工具的必须品 使用前需要配置环境变量:1.变量名为ERLANG_HOME,变量值为安装Erlang...
本资源是 适用于 linux centos 的 最新版 otp_src_21.3.tar.gz
Erlang otp_src_20.3.tar.gz linux centos otp-OTP-20.0.tar.gz 可兼容rabbitmq3.7.0
erlang_otp_20.3_man开发手册,erlang_otp_20.3_man开发手册,erlang_otp_20.3_man开发手册
erlang 22.3版本 erlang_otp_src_22.3 安装说明https://blog.csdn.net/tangcv/article/details/111841082
otp_win64_22.1的官方地址下载太慢,共享一下otp_Erlang_win64_22.1百度云下载地址
Erlang最新版本 25.0.3 windows 安装文件 解压直接安装 5个币-----------------------------------------------------------------------------------------------------------------------------------------------...
此文件为otp_src_20.2.tar.gz 的二次压缩文件 解压先用unzip otp_src_20.2.zip 出来, 然后就是安装时的 tar -zxvf otp_src_20.2.tar.gz内容了, 此文件为了自己使用是方便找到,请把分数定为1分,谢谢
Erlang opt_win64 20.2 windows exe 安装包 Erlang 20.2 is the upcoming version of Erlang For Windows x64 installer 截至2018.01.25 groovy最新最稳定版本
erlang官网下载速度太慢了,无法忍受,erlang_otp_src_22.3.tar.gz+rabbitmq-server-3.8.3-1.el6.noarch.rpm
erlang_otp_22.2_win64.exe & rabbitmq-server-3.8.3.exe
Erlang是一种通用的面向并发的编程语言,它有瑞典电信设备制造商爱立信所辖的CS-Lab开发, 目的是创造一种可以应对大规模并发活动的编程语言和运行环境。
Erlang 20.1 is the upcoming version of Erlang For doc 截至2017.11.09 groovy最新最稳定版本 MD5: 7840521e80dbb394852f265ef3e04744 大小:31.5 MB
通用 TCP 服务器 通用 TCP 服务器( gen_tcp_server ) 是一种 Erlang 行为,提供快速简便的方法将 TCP 服务器功能添加到您的应用程序。 它被实现为管理 TCP 连接的主管,因为它是孩子。如何使用它? 运行make来构建。...
erlang linux压缩包 otp_src_24.3.2.tar.gz
centOs安装下载erlang包otp_src_18.3.tar.gzotp_src_18.3.tar.gzotp_src_18.3.tar.gzotp_src_18.3.tar.gz
erlang centos 源码安装包 otp_src_23.1.tar.gz,erlang 官网下载是真慢,每次下载1-2个小时
otp_win64_24.1.7.exe
rabbitmq安装前的环境安装,Erlang23.0 Windows64安装包,官网下载了几个小时