Revision as of 19:15, 3 February 2011 (edit) Dae (Talk | contribs) m ← Previous diff |
Revision as of 11:22, 28 August 2012 (edit) (undo) Kjopeskoene (Talk | contribs) m 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 ]] | + | |