Erlang新手:为什么我必须重新启动才能加载新代码

时间:2013-10-26 06:55:11

标签: erlang

我正在尝试在Erlang中编写第一个程序来实现客户端和服务器之间的消息通信。理论上,服务器在没有收到来自客户端的消息时退出,但每次编辑客户端代码并再次运行服务器时,它都会执行旧代码。我必须^ g> q> erl> [重新输入命令]才能看到新代码。

-module(srvEsOne).

%%
%% export functions
%%

-export([start/0]).

%%function definition

start()->
    io:format("Server: Starting at pid: ~p \n",[self()]),
    case lists:member(serverEsOne, registered()) of
        true ->
            unregister(serverEsOne);                            %if the token  is present, remove it
        false ->
            ok
    end,
    register(serverEsOne,self()),
    Pid = spawn(esOne, start,[self()]),
    loop(false, false,Pid).

%
loop(Prec, Nrec,Pd)->
    io:format("Server: I am waiting to hear from: ~p \n",[Pd]),
    case Prec of
        true ->
            case Nrec of
                true ->     
                    io:format("Server: I reply to ~p \n",[Pd]),
                    Pd ! {reply, self()},
                    io:format("Server: I quit \n",[]),
                    ok;
                false ->
                    receiveLoop(Prec,Nrec,Pd)
            end;
        false ->
            receiveLoop(Prec,Nrec,Pd)
    end.

receiveLoop(Prec,Nrec,Pid) ->
    receive
        {onPid, Pid}->
            io:format("Server: I received a message to my pid from ~p \n",[Pid]),
            loop(true, Nrec,Pid);
        {onName,Pid}->
            io:format("Server: I received a message to name from ~p \n",[Pid]),
            loop(Prec,true,Pid)
    after
        5000->
            io:format("Server: I received no messages, i quit\n",[]),
            ok
    end.

客户端代码读取

-module(esOne).

-export([start/1, func/1]).

start(Par) ->
    io:format("Client: I am ~p, i was spawned by the server: ~p \n",[self(),Par]),

    spawn(esOne, func, [self()]),
    io:format("Client: Now I will try to send a message to: ~p \n",[Par]),
    Par ! {self(), hotbelgo},
    serverEsOne ! {self(), hotbelgo},

    ok.



func(Parent)->
    io:format("Child: I am ~p, i was spawned from ~p \n",[self(),Parent]).

服务器无法从客户端收到消息,但在我能以更直接的方式尝试更改代码之前,我无法明智地开始调试。

2 个答案:

答案 0 :(得分:2)

当你修改模块时,你需要编译它。

如果使用命令c(模块)或c(模块,[options])在erlang shell中执行此操作,则模块的新编译版本将自动加载到该shell中。它将被您启动的所有新流程使用。

对于那个活着且已经使用它的人来说解释起来更复杂,我认为这不是你所要求的。

如果你运行了几个erlang shell,那么只有编译模块的那个会加载它。这意味着在另一个shell中,如果模块先前已加载,基本上如果您已在这些shell中使用该模块,即使相应的进程已终止,也会忽略新版本。

如果使用命令erlc进行编译,则相同。

在所有这些情况下,您需要在shell中使用命令l(module)显式加载模块。

答案 1 :(得分:0)

您的服务器循环仅包含本地函数调用。仅当存在远程(或外部)函数调用时才会更改运行代码。所以你必须先导出你的循环函数:

-export([loop/3]).

然后您必须将函数loop/3中的所有receiveLoop/3次调用更改为

?MODULE:loop(...)

或者,您可以使用receiveLoop/3执行相同的操作。严肃应用程序的最佳实践是按需求进行热代码交换,因此只有在收到一些特殊消息后才能将loop/3更改为远程/外部。