2013-10-26 108 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

相關問題