我们将展示如何结合BIF monitor_node/2和向远程节点的注册进程发送消息的能力。我们将实现一个非常简单的银行服务,用以处理远程站点的请求,比如ATM机上存款、取款业务。这里我用的是自己机器上的两个不同的节点,客户端为:client@wae01020199woobest.com  服务端为server@wae01020199woobest.com。两个节点分别处理客户端与服务端的逻辑。 客户端:主要封装了三个接口,ask(查询某人的存储信息),desposit(存储某人的信息,{name,money}),withdraw(取钱操作,{name,money})。这里用了monitor_node(node,true)来检查网络的连接,只要未连接上,被连接进程将向该进程发送{nodedown, nodeid},只有才第二个参数为true的时候才会进行监听,如果连接不存在,且monitor_node/2被调用,系统将尝试建立连接;若连接建立失败则投递一个nodedown消息。若针对同一节点连续两次调用monitor_node/2则在节点失败时将投递两条nodedown消息。

 1 -module(bank_client).
 2 -export([ask/1, deposit/2, withdraw/2]).
 3 
 4 head_office() -> 'server@wae01020199.woobest.com'.
 5 
 6 ask(Who) -> call_back({ask, Who}).
 7 deposit(Who, Amount) -> call_back({deposit, Who, Amount}).
 8 withdraw(Who, Amount) -> call_back({withdraw, Who, Amount}).
 9 
10 call_back(Msg) ->
11     Headoffice = head_office(),
12     monitor_node(Headoffice, true),
13     {bank_server, Headoffice} ! {self(), Msg},
14     receive
15         {bank_server, Reply} ->
16             monitor_node(Headoffice, false),
17             Reply;
18         {nodedown, Headoffice} ->
19             no
20     end.

 

   服务端:首先start()方法注册一个bank_serser进程,执行server([]),此时参数为[]。在server中接受消息,ask,deposit,withdraw,例如接受ask(Who)后,返回client(From) {bank_server,lookup(Who,Data)},即为在Data中查找Who的数值。然后在client中接受后关闭监听进程,并将数据输出到控制台。在接受deposit,withdraw时处理方式类似。

 1 -module(bank_server).
 2 -export([start/0, server/1]).
 3 
 4 start() ->
 5     register(bank_server, spawn(bank_server, server, [[]])).
 6 
 7 server(Data) ->
 8     receive
 9         {From, {deposit, Who, Amount}} ->
10             From ! {bank_server, ok},
11             server(deposit(Who, Amount, Data));
12         {From, {ask, Who}} ->
13             From ! {bank_server, lookup(Who, Data)},
14             server(Data);
15         {From, {withdraw, Who, Amount}} ->
16             case lookup(Who, Data) of
17                 undefined ->
18                     From ! {bank_server, no},
19                     server(Data);
20                 Balance when Balance > Amount ->
21                     From ! {bank_server, ok},
22                     server(deposit(Who, -Amount, Data));
23                 _ ->
24                     From ! {bank_server, no},
25                     server(Data)
26             end
27     end.
28 
29 lookup(Who, [{Who, Value} | _]) -> Value;
30 lookup(Who, [_|T]) -> lookup(Who, T);
31 lookup(_, _) -> undefined.
32 
33 deposit(Who, X, [{Who, Balance}|T]) ->
34     [{Who, Balance + X}|T];
35 deposit(Who, X, [H|T]) ->
36     [H|deposit(Who, X, T)];
37 deposit(Who, X, []) ->
38     [{Who, X}].


  这里说明下自己创建两个节点的过程。client:在bank_client所在目录下以管理员权限运行cmd,然后输入erl -name client。。。以client命名方式打开erlang shell。同样在bank_server中,打开cmd输入erl -name server。。。打开erlang shell。这里说一下,启动可以用 erl -name server ,也可以用erl -sname server,区别在于   The node name will beName@Host, where Host is the fully qualified host name of the current host. For short names, use flag-sname instead.  

 posted on 2017-03-10 10:03  fengcl_matrix  阅读(389)  评论(0)    收藏  举报