0

我正在用 Erlang 开发一个简单的框架来处理 2 人回合制游戏。代码如下:

-module(game).
-export([start_server/0,generate_server/0,add_player/0,remove_player/0]).


generate_server() ->
Table_num = 0,
Player_num = 0,
io:format("Server generated...~n", []),
io:format("The current number of tables is ~w~n", [Table_num]),
io:format("The current number of players is ~w~n", [Player_num]),
receive
    login ->
        io:format("A new player has connected!~n", []),
        New = Player_num + 1,
        io:format("The current number of players is ~w~n", [New]);
    logout ->
        io:format("You have beeen succesfully disconnected~n", [])
end.



start_server() ->
    io:format("Welcome player!~nInitializing game...~n", []),
    io:format("Generating server...~n", []),
    register(server,spawn(game, generate_server, [])).


add_player() ->
    server ! login.


remove_player() ->
    server ! logout.

运行此代码时有两个主要问题:

  1. 当我执行 add_player() 然后 remove_player() 时,第二个函数崩溃并出现异常
  2. 如果我在一个终端窗口上启动程序,然后在第二个终端窗口上执行 add_player() ,我会收到错误消息。我应该怎么做才能在多个终端窗口上运行它?

任何帮助将不胜感激。

4

2 回答 2

3

1/您的服务器中没有循环。当您启动它时,经过一些打印后,它会等待接收语句。

当它收到登录消息时,它执行操作,然后服务器代码完成;该进程死亡并且未注册。所有变量都消失了,VM 清理了内存......

因此,稍后,任何向服务器发送消息的进程都会崩溃,因为您使用的是不再注册的名称。

要使其正常工作,您应该保留一个已连接玩家的列表(例如在列表中)并使用此列表作为参数调用服务器循环。

generate_server(Tlist,Plist) ->
io:format("The current number of tables is ~w~n", [length(Tlist)]),
io:format("The current number of players is ~w~n", [length(Plist)]),
receive
    {login,Name} ->
        io:format("A new player ~p has connected!~n", [Name]),
        generate_server(Tlist,[Name|Plist]);
    {logout,Name} ->
        io:format("You have beeen succesfully disconnected~n", []),
        generate_server(Tlist,lists:delete(Name,Plist))
end.

并且对 generate_server 的调用由

register(server,spawn(game, generate_server, [[],[]]))

2/ 为了在 2 个不同节点之间使用 erlang 消息,您需要:

  • 共享同一个 erlang coockie
  • 发现节点(例如使用 netadm)
  • 获取服务器 pid 或使用全球注册名称

请参阅http://learnyousomeerlang.com/distribunomicon#alone-in-the-dark上的示例

于 2012-12-05T20:04:22.200 回答
1

您错过了loop服务器的主体。您的程序崩溃,因为服务器只收到一条消息并退出。考虑下面的另一个版本的服务器:

生成服务器()->
    表数 = 0,
    Player_num = 0,
    io:format("服务器生成...~n", []),
    io:format("当前表数为~w~n", [Table_num]),
    io:format("当前玩家人数为~w~n", [Player_num]),
    环形([])。
循环(玩家)-> 收到 {From,{login,PlayerId}} -> io:format("一个新玩家连接了!~n", []), io:format("当前玩家人数为~w~n", [New]), NewPlayers = 案例列表:成员(PlayerId,Players) 真-> 从 !{login_failed,exists}, 球员; 假-> 从 !{login_success,true}, [玩家ID|玩家] 结尾, 循环(新玩家); {From,{logout,PlayerId}} -> NewPlayers = 案例列表:成员(PlayerId,Players) 真-> 从 !{注销,好的}, 玩家——[PlayerId]; 假-> 从 !{注销,失败}, 球员 结束,
循环(新玩家); _ -> 循环(玩家) 结尾。
那里; 看起来好多了。

于 2012-12-06T05:57:49.047 回答