Getting started with processes

From Erlang Community

(Difference between revisions)
Revision as of 19:15, 3 February 2011 (edit)
Dae (Talk | contribs)
m (fix link)
← Previous diff
Revision as of 11:22, 28 August 2012 (edit) (undo)
Kjopeskoene (Talk | contribs)
m (nike free adidas sko)
Next diff →
Line 1: Line 1:
-==Author==+http://www.kjopeskoene.com
-Doug Edmunds+kvinner Nike Free 3.0 Basketball Sko Adidas Forum Sko Fotballsko Adidas Free Sko Adidas Jeremy Scott Sko Adidas Porsch Sko Nike T?fler Android & DC Sko Luksus Vesker Puma Sko Vinter Brand Parka
- +http://www.kjopeskoene.com/kvinner-nike-free-30-c-79_80.html
-==More getting started with processes==+http://www.kjopeskoene.com/kvinner-nike-free-50-c-79_81.html
- +http://www.kjopeskoene.com/kvinner-nike-free-70-c-79_82.html
-The distro doc "Getting started with Erlang" has sample code called the "3.5 A Larger Example" and "4.3 The Larger Example with Robustness Added". I think it would be helpful to see how this example can be broken into two separate modules (one for the server and one for the clients). The code follows. +http://www.kjopeskoene.com/kvinner-nike-free-run-c-79_83.html
- +
-Please note that only the clients need to know the server's node information, since the clients initiate the contact with the server. You will have to modify the server_node() function in the m_client.erl file to correspond to your own server location. I developed this on windows xp, so I used a 'shortcut' to werl.exe, adding the -sname flag to the application line, i.e., +
-c:\somepath\erlang\bin\werl -sname m_server_node.+
- +
-I have purposely renamed various parts to show which is which (instead of referring to 'messenger' everywhere.+
- +
-For someone new to the use of processes, the more examples which show variations on the basic principles, the better.+
- +
--- Doug Edmunds+
- +
-Other materials to look at: [Click here | http://erlang.dougedmunds.com]+
- +
-code for m_server.erl:+
- +
-<code>+
-%% show how different files can be on different nodes,+
-%% and still communicate+
- +
--module(m_server).+
--export([start_server/0, server/0]).+
- +
-%%% This is the server process for the "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 server+
-start_server() ->+
- register(the_messenger, spawn(m_server, server, [])).+
- +
-%%% Server adds a new user to the user list+
-server_logon(From, Name, User_List) ->+
- %% check if logged on anywhere else+
- case lists:keymember(Name, 2, User_List) of+
- true ->+
- From ! {the_messenger, stop, user_exists_at_other_node}, %reject logon+
- User_List;+
- false ->+
- From ! {the_messenger, logged_on},+
- link(From),+
- [{From, Name} | User_List] %add user to the list+
- end.+
- +
-%%% Server deletes a user from the user list+
-server_logoff(From, User_List) ->+
- lists:keydelete(From, 1, User_List).+
- +
- +
-%%% Server transfers a message between user+
-server_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 ! {the_messenger, stop, you_are_not_logged_on};+
- {value, {_, Name}} ->+
- server_transfer(From, Name, To, Message, User_List)+
- end.+
- +
-%%% If the user exists, send the message+
-server_transfer(From, Name, To, Message, User_List) ->+
- %% Find the receiver and send the message+
- case lists:keysearch(To, 2, User_List) of+
- false ->+
- From ! {the_messenger, receiver_not_found};+
- {value, {ToPid, To}} ->+
- ToPid ! {message_from, Name, Message}, +
- From ! {the_messenger, sent} +
- end.+
- +
- +
-</code> +
- +
-code for m_client.erl:+
- +
-<code>+
- +
-%% show how different files can be on different nodes,+
-%% and still communicate+
- +
--module(m_client).+
--export([logon/1, logoff/0, message/2, client/2]).+
- +
-%%% Change the function below to return the name of the node where the+
-%%% messenger server runs+
-%%% Client needs to know this location+
-server_node() ->+
- m_server_node@sparky.+
- +
- +
-%%% User Commands+
-logon(Name) ->+
- case whereis(mess_client) of +
- undefined ->+
- register(mess_client, +
- spawn(m_client, 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},+
- ok+
-end.+
- +
-%%% The client process which runs on each user node+
-client(Server_Node, Name) ->+
- {the_messenger, Server_Node} ! {self(), logon, Name},+
- await_result(),+
- client(Server_Node).+
- +
-client(Server_Node) ->+
- receive+
- logoff ->+
- exit(normal);+
- {message_to, ToName, Message} ->+
- {the_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 server+
-await_result() ->+
- receive+
- {the_messenger, stop, Why} -> % Stop the client +
- io:format("~p~n", [Why]),+
- exit(normal);+
- {the_messenger, What} -> % Normal response+
- io:format("~p~n", [What])+
- after 5000 ->+
- io:format("No response from server~n", []),+
- exit(timeout)+
- end.+
- +
-</code>+
- +
-Here's section 4.3 of Getting Started with Erlang, which combines both server and client. Notice that server_node/0 is placed at the beginning of the code, but is really part of the client functions:+
- +
-<code>+
-%%% 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 runs+
-server_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 server+
-start_server() ->+
- register(messenger, spawn(messenger, server, [])).+
- +
-%%% Server adds a new user to the user list+
-server_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 list+
-server_logoff(From, User_List) ->+
- lists:keydelete(From, 1, User_List).+
- +
- +
-%%% Server transfers a message between user+
-server_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 message+
-server_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 Commands+
-logon(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},+
- ok+
-end.+
- +
-%%% The client process which runs on each user node+
-client(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 server+
-await_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.+
- +
-</code>+
- +
-[[Category:Articles ]]+

Revision as of 11:22, 28 August 2012

http://www.kjopeskoene.com kvinner Nike Free 3.0 Basketball Sko Adidas Forum Sko Fotballsko Adidas Free Sko Adidas Jeremy Scott Sko Adidas Porsch Sko Nike T?fler Android & DC Sko Luksus Vesker Puma Sko Vinter Brand Parka http://www.kjopeskoene.com/kvinner-nike-free-30-c-79_80.html http://www.kjopeskoene.com/kvinner-nike-free-50-c-79_81.html http://www.kjopeskoene.com/kvinner-nike-free-70-c-79_82.html http://www.kjopeskoene.com/kvinner-nike-free-run-c-79_83.html

Erlang/OTP Projects
Personal tools