Erlang服务器编程思想和实现

-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(Request, State),               From ! {Name, Response},               loop(Name, Mod, State1)       end. 

这段代码是erlang的标准服务器程序,下面写一个回调函数来运行测试。

name_server.erl

-module(name_server).   -export([init/0, add/2, whereis/1, handle/2]).   -import(server1, [rpc/2]).      %% client routines   add(Name, Place) -> rpc(name_server, {add, Name, Place}).   whereis(Name)    -> rpc(name_server, {whereis, Name}).      %% callback routines   init() -> dict:new().      handle({add, Name, Place}, Dict) -> {ok, dict:store(Name, Place, Dict)};   handle({whereis, Name}, Dict)    -> {dict:find(Name, Dict), Dict}.

首先看后面的代码1.他负责回调服务器程序,处理其他进程发货来的请求2.相当于定义接口。

如下运行程序:

erlc *.erl   

Eshell V5.6.5  (abort with ^G)   1> server1:start(name_server, name_server).   true   2> nameserver:add("lengzijian","go to school").   ** exception error: undefined function nameserver:add/2   3> name_server:add("lengzijian","go to school").   ok   4> name_server:whereis("lengzijian").   {ok,"go to school"}   5>   

如果读者细心可以发现,这段代码里面并没有spawn这样的创建进程的命令,不错,这个服务器程序完全是顺序性代码,也许有人质疑这样做的意义,不要急这才刚刚开始

2.server2:支持事务的服务器程序

接下来要向大家展示的是,当服务器宕机,客户端回或得到异常,然后做相应的处理。

server2.erl

-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(Request, OldState) of           {Response, NewState} ->               From ! {Name, ok, Response},               loop(Name, Mod, NewState)           catch           _:Why ->               log_the_error(Name, Request, Why),               %% send a message to cause the client to crash               From ! {Name, crash},               %% loop with the *original* state               loop(Name, Mod, OldState)           end       end.      log_the_error(Name, Request, Why) ->       io:format("Server ~p request ~p ~n"             "caused exception ~p~n",              [Name, Request, Why]).    

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wywdpx.html