4、可靠性
4.1 逾時設定-module(tut19).-export([start_ping/1, start_pong/0, ping/2, pong/0]).ping(0, Pong_Node) -> io:format("ping finished~n", []);ping(N, Pong_Node) -> {pong, Pong_Node} ! {ping, self()}, receive pong -> io:format("Ping received pong~n", []) end, ping(N - 1, Pong_Node).pong() -> receive {ping, Ping_PID} -> io:format("Pong received ping~n", []), Ping_PID ! pong, pong() after 5000 -> io:format("Pong timed out~n", []) end.start_pong() -> register(pong, spawn(tut19, pong, [])).start_ping(Pong_Node) -> spawn(tut19, ping, [3, Pong_Node]).After we have compiled this and copied the tut19.beam file to the necessary directories: On (pong@kosken): (pong@kosken)1> tut19:start_pong().truePong received pingPong received pingPong received pingPong timed outOn (ping@gollum): (ping@gollum)1> tut19:start_ping(pong@kosken).<0.36.0>Ping received pongPing received pongPing received pongping finished (The timeout is set in: pong() -> receive {ping, Ping_PID} -> io:format("Pong received ping~n", []), Ping_PID ! pong, pong() after 5000 -> io:format("Pong timed out~n", []) end.4.2 差錯處理-module(tut20).-export([start/1, ping/2, pong/0]).ping(N, Pong_Pid) -> link(Pong_Pid), ping1(N, Pong_Pid).ping1(0, _) -> exit(ping);ping1(N, Pong_Pid) -> Pong_Pid ! {ping, self()}, receive pong -> io:format("Ping received pong~n", []) end, ping1(N - 1, Pong_Pid).pong() -> receive {ping, Ping_PID} -> io:format("Pong received ping~n", []), Ping_PID ! pong, pong() end.start(Ping_Node) -> PongPID = spawn(tut20, pong, []), spawn(Ping_Node, tut20, ping, [3, PongPID]).(s1@bill)3> tut20:start(s2@kosken).Pong received ping<3820.41.0>Ping received pongPong received pingPing received pongPong received pingPing received pong%%--------------------------------------------------------------module(tut21).-export([start/1, ping/2, pong/0]).ping(N, Pong_Pid) -> link(Pong_Pid), ping1(N, Pong_Pid).ping1(0, _) -> exit(ping);ping1(N, Pong_Pid) -> Pong_Pid ! {ping, self()}, receive pong -> io:format("Ping received pong~n", []) end, ping1(N - 1, Pong_Pid).pong() -> process_flag(trap_exit, true), pong1().pong1() -> receive {ping, Ping_PID} -> io:format("Pong received ping~n", []), Ping_PID ! pong, pong1(); {'EXIT', From, Reason} -> io:format("pong exiting, got ~p~n", [{'EXIT', From, Reason}]) end.start(Ping_Node) -> PongPID = spawn(tut21, pong, []), spawn(Ping_Node, tut21, ping, [3, PongPID]).(s1@bill)1> tut21:start(s2@gollum).<3820.39.0>Pong received pingPing received pongPong received pingPing received pongPong received pingPing received pongpong exiting, got {'EXIT',<3820.39.0>,ping}4.3 增強可靠性的大型樣本%%% Message passing utility. %%% User interface:%%% login(Name)%%% One user at a time can log in from each Erlang node in the%%% system messenger: and choose a suitable Name. If the Name%%% is already logged in at another node or if someone else is%%% already logged in at the same node, login will be rejected%%% with a suitable error message.%%% logoff()%%% Logs off anybody at at node%%% message(ToName, Message)%%% sends Message to ToName. Error messages if the user of this %%% function is not logged on or if ToName is not logged on at%%% any node.%%%%%% One node in the network of Erlang nodes runs a server which maintains%%% data about the logged on users. The server is registered as "messenger"%%% Each node where there is a user logged on runs a client process registered%%% as "mess_client" %%%%%% Protocol between the client processes and the server%%% ----------------------------------------------------%%% %%% To server: {ClientPid, logon, UserName}%%% Reply {messenger, stop, user_exists_at_other_node} stops the client%%% Reply {messenger, logged_on} logon was successful%%%%%% When the client terminates for some reason%%% To server: {'EXIT', ClientPid, Reason}%%%%%% To server: {ClientPid, message_to, ToName, Message} send a message%%% Reply: {messenger, stop, you_are_not_logged_on} stops the client%%% Reply: {messenger, receiver_not_found} no user with this name logged on%%% Reply: {messenger, sent} Message has been sent (but no guarantee)%%%%%% To client: {message_from, Name, Message},%%%%%% Protocol between the "commands" and the client%%% ---------------------------------------------- %%%%%% Started: messenger:client(Server_Node, Name)%%% To client: logoff%%% To client: {message_to, ToName, Message}%%%%%% Configuration: change the server_node() function to return the%%% name of the node where the messenger server runs-module(messenger).-export([start_server/0, server/0, logon/1, logoff/0, message/2, client/2]).%%% Change the function below to return the name of the node where the%%% messenger server runsserver_node() -> messenger@super.%%% This is the server process for the "messenger"%%% the user list has the format [{ClientPid1, Name1},{ClientPid22, Name2},...]server() -> process_flag(trap_exit, true), server([]).server(User_List) -> receive {From, logon, Name} -> New_User_List = server_logon(From, Name, User_List), server(New_User_List); {'EXIT', From, _} -> New_User_List = server_logoff(From, User_List), server(New_User_List); {From, message_to, To, Message} -> server_transfer(From, To, Message, User_List), io:format("list is now: ~p~n", [User_List]), server(User_List) end.%%% Start the serverstart_server() -> register(messenger, spawn(messenger, server, [])).%%% Server adds a new user to the user listserver_logon(From, Name, User_List) -> %% check if logged on anywhere else case lists:keymember(Name, 2, User_List) of true -> From ! {messenger, stop, user_exists_at_other_node}, %reject logon User_List; false -> From ! {messenger, logged_on}, link(From), [{From, Name} | User_List] %add user to the list end.%%% Server deletes a user from the user listserver_logoff(From, User_List) -> lists:keydelete(From, 1, User_List).%%% Server transfers a message between userserver_transfer(From, To, Message, User_List) -> %% check that the user is logged on and who he is case lists:keysearch(From, 1, User_List) of false -> From ! {messenger, stop, you_are_not_logged_on}; {value, {_, Name}} -> server_transfer(From, Name, To, Message, User_List) end.%%% If the user exists, send the messageserver_transfer(From, Name, To, Message, User_List) -> %% Find the receiver and send the message case lists:keysearch(To, 2, User_List) of false -> From ! {messenger, receiver_not_found}; {value, {ToPid, To}} -> ToPid ! {message_from, Name, Message}, From ! {messenger, sent} end.%%% User Commandslogon(Name) -> case whereis(mess_client) of undefined -> register(mess_client, spawn(messenger, client, [server_node(), Name])); _ -> already_logged_on end.logoff() -> mess_client ! logoff.message(ToName, Message) -> case whereis(mess_client) of % Test if the client is running undefined -> not_logged_on; _ -> mess_client ! {message_to, ToName, Message}, okend.%%% The client process which runs on each user nodeclient(Server_Node, Name) -> {messenger, Server_Node} ! {self(), logon, Name}, await_result(), client(Server_Node).client(Server_Node) -> receive logoff -> exit(normal); {message_to, ToName, Message} -> {messenger, Server_Node} ! {self(), message_to, ToName, Message}, await_result(); {message_from, FromName, Message} -> io:format("Message from ~p: ~p~n", [FromName, Message]) end, client(Server_Node).%%% wait for a response from the serverawait_result() -> receive {messenger, stop, Why} -> % Stop the client io:format("~p~n", [Why]), exit(normal); {messenger, What} -> % Normal response io:format("~p~n", [What]) after 5000 -> io:format("No response from server~n", []), exit(timeout) end.