我们将展示如何结合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
浙公网安备 33010602011771号