2013-10-26 66 views
1

我正在尝试在Erlang中编写第一个程序,该程序会影响客户端和服务器之间的消息通信。从理论上讲,服务器在没有收到来自客户端的消息时退出,但是每次我编辑客户端代码并再次运行服务器时,它都会执行旧代码。我必须要让^ G> q> erl> [重新输入命令]才能看到新的代码。Erlang新手:为什么我必须重新启动才能加载新代码

-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]). 

服务器无法接收来自客户端的消息,但我不能理智地开始调试,直到我可以尝试更改代码更直接的方式。

+0

也许这可以帮助你? [Erlang中的热代码替换](http://stackoverflow.com/questions/11968809/hot-code-replacement-in-erlang?rq=1) – baltov

回答

2

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

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

对于那些活着并且已经使用它的人来说更复杂一些,我认为这不是你要求的。

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

如果您使用命令erlc进行编译,也是如此。

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

+0

你钉了它!我使用的OSX终端有两个选项卡 - 我在一个编译器中运行代码,另一个选项卡看不到新代码。 Thx –

0

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

-export([loop/3]). 

,然后你必须在功能上receiveLoop/3所有loop/3呼叫变为

?MODULE:loop(...) 

或者你可以做同样的事情,而不是receiveLoop/3。对于严重应用程序的最佳做法是根据需求进行热门代码交换,因此只有在收到特殊消息后才将loop/3更改为远程/外部。

+1

只是想强调最后一点,您通常不希望总是获取新版本的代码,而是以受控的方式更改版本。这样可以让你在升级时做必要的事情。 – rvirding

相关问题