Getting started with processes
From Erlang Community
| Revision as of 21:06, 4 August 2007 (edit) Dae (Talk | contribs) (Additional tutorial material to tie into the 'getting started' doc that comes with the distro) ← Previous diff |
Revision as of 21:10, 4 August 2007 (edit) (undo) Dae (Talk | contribs) m Next diff → |
||
| Line 1: | Line 1: | ||
| + | ==Author== | ||
| + | Doug Edmunds | ||
| + | |||
| + | ==More getting started with processes== | ||
| + | |||
| The doc "Getting started with Erlang" has sample code called the "A Larger Example" and "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. | The doc "Getting started with Erlang" has sample code called the "A Larger Example" and "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. | ||
| Line 156: | Line 161: | ||
| - | [[Category: | + | [[Category:Articles ]] |
Revision as of 21:10, 4 August 2007
Author
Doug Edmunds
More getting started with processes
The doc "Getting started with Erlang" has sample code called the "A Larger Example" and "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.
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
code for m_server.erl:
%% 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 for m_client.erl:
%% 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.
|

Digg It
Del.icio.us
Reddit
Facebook
Stumble Upon
Technorati

