Chinaunix首页 | 论坛 | 博客
  • 博客访问: 752899
  • 博文数量: 130
  • 博客积分: 2951
  • 博客等级: 少校
  • 技术积分: 1875
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-04 18:32
文章分类

全部博文(130)

文章存档

2013年(1)

2012年(129)

分类: Python/Ruby

2012-03-05 16:43:36


  1. %%% Message passing utility.
  2. %%% User interface:
  3. %%% logon(Name)
  4. %%% One user at a time can log in from each Erlang node in the
  5. %%% system messenger: and choose a suitable Name. If the Name
  6. %%% is already logged in at another node or if someone else is
  7. %%% already logged in at the same node, login will be rejected
  8. %%% with a suitable error message.
  9. %%% logoff()
  10. %%% Logs off anybody at at node
  11. %%% message(ToName, Message)
  12. %%% sends Message to ToName. Error messages if the user of this
  13. %%% function is not logged on or if ToName is not logged on at
  14. %%% any node.
  15. %%%
  16. %%% One node in the network of Erlang nodes runs a server which maintains
  17. %%% data about the logged on users. The server is registered as "messenger"
  18. %%% Each node where there is a user logged on runs a client process registered
  19. %%% as "mess_client"
  20. %%%
  21. %%% Protocol between the client processes and the server
  22. %%% ----------------------------------------------------
  23. %%%
  24. %%% To server: {ClientPid, logon, UserName}
  25. %%% Reply {messenger, stop, user_exists_at_other_node} stops the client
  26. %%% Reply {messenger, logged_on} logon was successful
  27. %%%
  28. %%% To server: {ClientPid, logoff}
  29. %%% Reply: {messenger, logged_off}
  30. %%%
  31. %%% To server: {ClientPid, logoff}
  32. %%% Reply: no reply
  33. %%%
  34. %%% To server: {ClientPid, message_to, ToName, Message} send a message
  35. %%% Reply: {messenger, stop, you_are_not_logged_on} stops the client
  36. %%% Reply: {messenger, receiver_not_found} no user with this name logged on
  37. %%% Reply: {messenger, sent} Message has been sent (but no guarantee)
  38. %%%
  39. %%% To client: {message_from, Name, Message},
  40. %%%
  41. %%% Protocol between the "commands" and the client
  42. %%% ----------------------------------------------
  43. %%%
  44. %%% Started: messenger:client(Server_Node, Name)
  45. %%% To client: logoff
  46. %%% To client: {message_to, ToName, Message}
  47. %%%
  48. %%% Configuration: change the server_node() function to return the
  49. %%% name of the node where the messenger server runs

  50. -module(messenger).
  51. -export([start_server/0, server/1, logon/1, logoff/0, message/2, client/2]).

  52. %%% Change the function below to return the name of the node where the
  53. %%% messenger server runs
  54. server_node() ->
  55.     messenger@Lizhuohua.

  56. %%% This is the server process for the "messenger"
  57. %%% the user list has the format [{ClientPid1, Name1},{ClientPid22, Name2},...]
  58. server(User_List) ->
  59.     %%% 我是服务器的消息处理的地方,等待消息中~~~
  60.     receive
  61.         {From, logon, Name} -> %%%咦,有客户来登陆了
  62.             io:format("4~n"),
  63.             New_User_List = server_logon(From, Name, User_List), %%%我是server,我需要记录所有的客户,调用server_logon来做这个事情吧
  64.             io:format("5~n"),
  65.             server(New_User_List);
  66.         {From, logoff} -> %%%哟, 有客户要走了。。。
  67.             New_User_List = server_logoff(From, User_List), %%%一路走好啊,我Server得把你从我得客户列表里删除掉。。。
  68.             server(New_User_List);
  69.         {From, message_to, To, Message} -> %%%咦,有客户想聊天?恩,从From这个pid的客户发过来的,
  70.                                             %%%我得用我Server的server_transfer(From, To, Message, User_List)函数来转发一下。
  71.             server_transfer(From, To, Message, User_List),
  72.             io:format("list is now: ~p~n", [User_List]),
  73.             server(User_List)
  74.     end.

  75. %%% Start the server
  76. start_server() ->
  77.     %%% 我是服务器,启动啦,创建了一个进程,去server(User_List)找我吧
  78.     register(messenger, spawn(messenger, server, [[]])).


  79. %%% Server adds a new user to the user list
  80. server_logon(From, Name, User_List) ->
  81.     %% check if logged on anywhere else
  82.     case lists:keymember(Name, 2, User_List) of %%%我是server,对了,我需要先看看已经记录的客户列表里有没有这个要登陆的新客户,
  83.                                                 %%%每个客户记录的格式用一个Tuple记录{客户的pid,客户的名字},我按名字查找每个Tuple好了,
  84.                                                 %%%客户的名字在Tuple里的所以是2(从1开始)
  85.         true -> %%%咦,这个客户已经在我的记录里了
  86.             From ! {messenger, stop, user_exists_at_other_node}, %那就拒绝他再次登陆吧,发给他一个stop的消息给他,内容是user_exists_at_other_node
  87.             User_List;
  88.         false ->%%%恩,这个客户不在已有的记录里,那就让他登陆吧。
  89.             From ! {messenger, logged_on}, %%%发给他一个登陆成功的消息
  90.             [{From, Name} | User_List] %add user to the list
  91.     end.

  92. %%% Server deletes a user from the user list
  93. server_logoff(From, User_List) ->
  94.     lists:keydelete(From, 1, User_List). %%%按照客户的pid在客户列表里查找,找到就删除吧 ,
  95.                                         %%%每个客户记录的格式用一个Tuple记录{客户的pid,客户的名字},我这次按pid查找每个Tuple好了,
  96.                                         %%%客户的pid在Tuple里的索引是1(从1开始)


  97. %%% Server transfers a message between user
  98. server_transfer(From, To, Message, User_List) ->
  99.     %% check that the user is logged on and who he is
  100.     case lists:keysearch(From, 1, User_List) of
  101.         false ->
  102.             From ! {messenger, stop, you_are_not_logged_on};
  103.         {value, {From, Name}} -> %%%keyserver函数返回的结果就是{value, Tuple},而这个Tuple又是由{From, Name}组成。
  104.             server_transfer(From, Name, To, Message, User_List) %%%继续转发
  105.     end.
  106. %%% If the user exists, send the message
  107. server_transfer(From, Name, To, Message, User_List) ->
  108.     %% Find the receiver and send the message
  109.     case lists:keysearch(To, 2, User_List) of
  110.         false ->
  111.             From ! {messenger, receiver_not_found};
  112.         {value, {ToPid, To}} ->
  113.             ToPid ! {message_from, Name, Message}, %%%终于可以给目的客户发消息了,恩,得把发送人告诉目的客户是谁发给他的
  114.             From ! {messenger, sent} %%%恩,还得给发送消息的客户一个回复,他还等着呢。。
  115.     end.


  116. %%% User Commands
  117. logon(Name) -> %%%我是客户端,我来登陆啦
  118.     case whereis(mess_client) of %%%找找我自己是不是已经存在
  119.         undefined -> %%%不存在
  120.             register(mess_client, %%%把自己注册为mess_client, 创建进程,去client(Server_Node, Name)看我的后续吧
  121.                      spawn(messenger, client, [server_node(), Name]));
  122.         _ -> already_logged_on
  123.     end.

  124. logoff() -> %%%没意思,我不想处于登陆状态了,我要下线了,88各位。
  125.     mess_client ! logoff. %%给自己发了一个logoff的消息

  126. message(ToName, Message) -> %%我是客户,我想跟别人聊聊天,用这个函数吧, ToName是我的聊天对象
  127.     case whereis(mess_client) of % Test if the client is running
  128.         undefined ->
  129.             not_logged_on;
  130.         _ -> mess_client ! {message_to, ToName, Message}, %%先给我自己一个消息,我要和别人聊天了, 进入client(Server_Node){message_to, ToName, Message}部分
  131.              ok
  132. end.


  133. %%% The client process which runs on each server node
  134. client(Server_Node, Name) ->
  135.     {messenger, Server_Node} ! {self(), logon, Name}, %%%我需要让Server知道我来登陆了,所以给Server发个logon的消息
  136.                                                         %%%把我自己的pid和Name作为参数发给Server, 下面看server(User_List)函数
  137.     await_result(), %%%恩。。发完了,我就用这个函数等待Server给我的返回值了
  138.     client(Server_Node). %%% 恩登陆成功,我进入我自己的消息世界喽 Client(Server_Node),等着Server给我发各种消息了

  139. client(Server_Node) ->
  140.     receive %%%我在等待Server给我发各种消息。。。。。~z~z~z
  141.         logoff ->
  142.             io:format("8~n"),
  143.             {messenger, Server_Node} ! {self(), logoff}, %%%唉,还是得让Server知道我走了,给Server发个消息吧
  144.             exit(normal);
  145.         {message_to, ToName, Message} ->
  146.             {messenger, Server_Node} ! {self(), message_to, ToName, Message}, %%%想和别人聊天,消息还得通过Server中转,麻烦,先给Server发个消息吧
  147.             await_result(); %%%我客户在这等结果了
  148.         {message_from, FromName, Message} -> %%%咦,Server给我发消息了,原来是有别的客户跟我说话呢。
  149.             io:format("Message from ~p: ~p~n", [FromName, Message])
  150.     end,
  151.     client(Server_Node).

  152. %%% wait for a response from the server
  153. await_result() ->
  154.     receive
  155.         {messenger, stop, Why} -> % Stop the client 呀,我被Server拒绝了,原因在Why里。。。 比如重复登陆被拒绝时。
  156.             io:format("~p~n", [Why]),
  157.             exit(normal); %%%被Server拒绝了还有啥脸面存活于世,我自杀算了。。
  158.         {messenger, What} -> % Normal response 恩,Server返回消息了,比如返回logon_on正常登陆的消息, 比如Server发送聊天消息后,告诉启动聊天的客户,消息已经sent
  159.             io:format("6~n"),
  160.             io:format("~p~n", [What])
  161.     end.
运行:
创建3个节点, windows上打开3个cmd,每个分别运行
erl.exe -sname messenger 生成messenger@hostname节点
erl.exe -sname node1     生成node1@hostname节点
erl.exe -sname node2     生成node2@hostname节点

然后在messenger@hostname节点上运行:
messenger:start_server().

之后在node1@hostname节点上运行:
messenger:logon(node1).
之后再node2@hostname节点上运行:
messenger:logon(node2).
可以启动聊天,在node1@hostname节点上运行:
messenger:message(node2, "hello")
最后是logoff,在node1@hostname节点上运行:
messenger:logoff()
阅读(1028) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~