如何使Erlang Client/Server与Config的参数/节点连接



我正在Erlang编写客户端/服务器系统,无法使其连接。它们应该使用的节点存储在配置文件中,这些节点在启动它们时加载。他们还使用多个分布式数据结构。问题是,我首先启动数据结构,然后服务器(工作正常(,但是当我启动客户端时,它不会连接到任何事物并引发异常。

服务器:

-module(server).
-export([startServer/0,loopServer/7,node/0,log/0,name/0]).
-compile({no_auto_import,[node/0]}).
-import(werkzeug, [get_config_value/2,lengthSL/1,logging/2,reset_timer/3,get_config_value/2]).
-import(erlang, [append/2]).
log() ->
    erlang:list_to_atom(lists:concat(["Server@", node(),".log"])).
node() ->
    {ok,Config} = file:consult("configs/server.cfg"), 
    {ok, Node} = werkzeug:get_config_value(node,Config),
    Node.
name() ->
    {ok,Config} = file:consult("configs/server.cfg"), 
    {ok, Name} = werkzeug:get_config_value(servername,Config),
    Name.

%%Startet den Server und die darin enthaltene Schleife
startServer() -> 
    {ok,Config} = file:consult("configs/server.cfg"), 
    {ok, Name} = get_config_value(servername,Config),
    %%CMEM initialisieren
    {ok, RemTime} = get_config_value(cmemtime,Config),
    CMEM = cmem:initCMEM(RemTime, log()),
    %%HBQ-Prozess erzeugen
    {ok,HBQName} = get_config_value(hbqname,Config),
    {ok,HBQNode} = get_config_value(node,Config),
    HBQ = {HBQName,HBQNode},
    {ok,Serverzeit} = get_config_value(serverzeit,Config),
    %%Zeitpunkt des Timer übergeben
    {ok, Timer} = timer:send_after(round(RemTime * 1000),Name,delServer),
    %%Prozess registrieren, Serverschleife mit allen Infos starten, plus NNr 1
    ServerPid = spawn(?MODULE, loopServer, [Name,CMEM,HBQ,Timer,Serverzeit,Config,1]),                                                          
    register(Name,ServerPid),
    %%HBQ initialisieren
    HBQ ! {ServerPid, {request,initHBQ}},
    {Config,CMEM,HBQ,ServerPid}.

loopServer(Name,CMEM,HBQ,Timer,Serverzeit,Config,NNr) ->
    receive
        %%Client fragt neue Nachrichten ab, dazu wird aus CMEM die aktuelle NNr für 
        %%den Client angefordert und mit der ClientPID an die HBQ weitergegeben
        {ClientPID,getmessages} ->
            NewTimer = reset_timer(Timer,Serverzeit,delServer),
            ClientNNr = cmem:getClientNNr(CMEM, ClientPID),
            HBQ ! {self(), {request, deliverMSG, ClientNNr, ClientPID}},
            logging(log(), lists:concat(["Server: Nachricht ", NNr, " wurde zugestellt.n"])),
            loopServer(Name,CMEM,HBQ,NewTimer,Serverzeit,Config,NNr);
        %%Nachricht soll in HBQ verschoben werden
        {dropmessage,[INNr,Msg,TSclientout]} ->
            NewTimer = reset_timer(Timer,Serverzeit,delServer),
            HBQ ! {self(), {request,pushHBQ,[INNr,Msg,TSclientout]}},
            receive
                {reply,ok} ->
                logging(log(), lists:concat(["Server: Nachricht ", INNr, " wurde in HBQ eingefuegt.n"]))
            end,
            loopServer(Name,CMEM,HBQ,NewTimer,Serverzeit,Config,NNr);
        %%Client fragt naechste NNr ab, diese wird dem Zustand des Server entnommen
        {ClientPID,getmsgid} ->
          NewTimer = reset_timer(Timer,Serverzeit,delServer),
          ClientPID ! {nid, NNr},
          NewNNr = NNr + 1,
          logging(log(), lists:concat(["Server: Nachrichtennumer ", NNr, " an ", erlang:pid_to_list(ClientPID), "gesendet.n"])),
          loopServer(Name,CMEM,HBQ,NewTimer,Serverzeit,Config,NewNNr);
        %%Server beendet sich selbst und zugleich die HBQ
        delServer ->
            HBQ ! {self(),{request,delHBQ}},
            receive
                {reply,ok} ->
                logging(log(), lists:concat([lists:concat(["Server: Downtime ", werkzeug:timeMilliSecond(), " von ", name() ,"n"])])),
                ok
            end
    end.

客户端:

-module(client).
-export([startClients/0,loopClient/4,spawnC/1,forLoop/3,mitServerVerbinden/6,configLaden/0]).
-import(werkzeug, [get_config_value/2]).
-import(timer, [apply_after/4]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%   Client  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%initClient
startClients() ->
  Config = configLaden(),
  {ok, ClientAnzahl} = werkzeug:get_config_value(clientanzahl, Config),
  {ok, ServerName} = werkzeug:get_config_value(servername, Config),
  {ok, ServerNode} = werkzeug:get_config_value(servernode, Config),
  ServerPid = {ServerName,ServerNode},
forLoop(ClientAnzahl, fun client:spawnC/1, ServerPid).

%%Hilfsfunktion fuer for-Schleife: Zaehlt runter,
%%ruft Funktion auf und gibt Ergebnisse als Liste zurueck
forLoop(Clients, Spawn, SPid) -> forLoop(Clients, Spawn, SPid, []).
forLoop(0, _Spawn, _SPid, ClientListe) -> ClientListe;
forLoop(Clients, Spawn, SPid, ClientListe) ->
  ClientListeNew = ClientListe ++ [Spawn(SPid)],
  ClientsNew = Clients - 1,
forLoop(ClientsNew, Spawn, SPid, ClientListeNew).
%%Neuen ClientProzess erzeugen
spawnC(ServerPid) ->
  Config = configLaden(),
  {ok, Lebenszeit} = werkzeug:get_config_value(lebenszeit, Config),
  {ok, Cookie} = werkzeug:get_config_value(cookie, Config),
  {ok, ServerNode} = werkzeug:get_config_value(servernode, Config),
  {ok, Wartezeit} = werkzeug:get_config_value(wartezeit, Config),
  ClientPid = erlang:spawn(?MODULE, mitServerVerbinden, [ServerPid, [], [], Wartezeit, ServerNode, Cookie]),
  timer:kill_after(Lebenszeit, ClientPid),
ClientPid.
%%mit Server Verbinden
mitServerVerbinden(ServerPid,Datei,NNummern,Wartezeit,ServerNode,Cookie) ->
  erlang:set_cookie(ServerNode,Cookie),
  pong = net_adm:ping(ServerNode),
loopClient(ServerPid,NNummern,Wartezeit,Datei).

%%loopClient
loopClient(ServerPid,NNummern,Wartezeit,Datei) ->
  %%Client wird zum Redakteur
  {NNummernNew, WartezeitNew, DateiNew} = nachrichtenSenden(5,ServerPid,NNummern,Wartezeit,Datei),
  %%Client wird zum Leser
  nachrichtenLesen(false, NNummernNew, ServerPid,DateiNew),
  %%Methode ruft sich selbst wieder auf
  loopClient(ServerPid, NNummernNew, WartezeitNew,DateiNew).

configLaden() ->
  {ok, Config} = file:consult("configs/client.cfg"),
  Config. 


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Redakteur %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%Nachricht soll vergessen werden
nachrichtenSenden(0,ServerPid,NNummern,Wartezeit,Datei) ->
  %%Naechste NNr beim Server anfragen
  ServerPid ! {self(),getmsgid},
  receive 
    %%Server sendet NNr
    {nid,NNr} ->
      %%Logeintrag
  werkzeug:logging(Datei,lists:concat([NNr, "te Nachricht um ", werkzeug:timeMilliSecond(), " vergessen zu senden. ******n"]))
    end,
  WartezeitNew = wartezeitBerechnen(Wartezeit),
  %%Rückgabewerte: Liste mit Nachrichtennummern fuer leser, neue Wartezeit, Logfile
  {NNummern,WartezeitNew,Datei};


%%Nachrichtennummer anfragen und erhalten, Nachricht schreiben
nachrichtenSenden(NachrichtenVorVergessen,ServerPid,NNummern,Wartezeit,Datei) ->
  Config = configLaden(),
  {ok, ServerNode} = werkzeug:get_config_value(servernode, Config),
  %%Naechste NNr beim Server anfragen
  ServerPid ! {self(),getmsgid},
  receive
    %%Server sendet NNr
    {nid,NNr} ->
     %%Nachricht schreiben
     Nachricht = nachrichtSchreiben(NNr),
      %%NNr zur Liste hinzufuegen fuer Leser
      NNummernNew = NNummern ++[NNr],
      timer:sleep(Wartezeit),
      %%Nachricht an Server senden
      ServerPid ! {dropmessage,[NNr,Nachricht,erlang:now()]},
      %%Logeintrag schreiben
      werkzeug:logging(Datei,lists:concat([Nachricht, " gesendet"])),
    %%Neue Wartezeit berechnen  
    WartezeitNew = wartezeitBerechnen(Wartezeit),
    %%Zaehler dekrementieren  
    NachrichtenVorVergessenNew = NachrichtenVorVergessen -1,
  %%Methode neu aufrufen
  nachrichtenSenden(ServerPid,NNummernNew,WartezeitNew,NachrichtenVorVergessenNew,Datei)
  end.

%%nachrichtSchreiben
nachrichtSchreiben(NNr) ->
  Config = configLaden(),
  {ok, Rechner} = werkzeug:get_config_value(rechner, Config),
  {ok, Praktikumsgruppe} = werkzeug:get_config_value(praktikumsgruppe, Config),
  {ok, Teamnummer} = werkzeug:get_config_value(teamnummer, Config),
lists:concat(["client@",Rechner, "_", Praktikumsgruppe, "_", Teamnummer, ": ", integer_to_list(NNr), "_te Nachricht. Sendezeit: ", werkzeug:timeMilliSecond()]).

%%Hilfsmethode: Intervall darf nicht kleiner als zwei Sekunden werden
minimumTime() -> 2000.
%%Berechnet das neue Zeitintervall, um die Haelfte groesser oder
%%kleiner als die alte Zeit, solange sie groesser gleich 2 Sekunden ist
wartezeitBerechnen(Wartezeit) -> 
    GroesserKleiner = werkzeug:bool_rand(),
  HaelfteZeit = trunc(max(Wartezeit * 0.5, minimumTime())),
  if
    GroesserKleiner ->
      Wartezeit + HaelfteZeit;
    true ->
      max(Wartezeit - HaelfteZeit, minimumTime())
end.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    Leser   %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

nachrichtenLesen(true,NNummern,ServerPid,Datei) -> ok;
nachrichtenLesen(false,NNummern,ServerPid,Datei) ->
  ServerPid ! {self(),getmessages},
  receive 
    {reply,Message,Terminated} ->
    nachrichtInLogSchreiben(Message,NNummern,Datei),
    nachrichtenLesen(Terminated,NNummern,ServerPid,Datei)
  end.
nachrichtInLogSchreiben([NNr,Msg,TSclientout,TShbqin,TSdlqin,TSdlqout],NNummern,Datei) ->
  Now = erlang:timestamp(),
  DLQInTrue = werkzeug:validTS(TSdlqin),
  DLQOutTrue = werkzeug:validTS(TSdlqout),
  DLQInZukunft = werkzeug:lessTS(Now, TSdlqin),
  DLQOutZukunft = werkzeug:lessTS(Now, TSdlqout),
  MsgVonGleichemClient = msgVonGleichemClient(NNr, Msg, NNummern),
  if
      DLQInTrue and DLQInZukunft ->
      Zeitunterschied = werkzeug:now2stringD(werkzeug:diffTS(TSdlqin, Now)),
      MsgNew = MsgVonGleichemClient ++ ", Zeitunterschied: " ++ Zeitunterschied,
      werkzeug:logging(Datei, MsgNew ++ "n");
    DLQOutTrue and DLQOutZukunft ->
      Zeitunterschied = werkzeug:now2stringD(werkzeug:diffTS(TSdlqout, Now)),
      MsgNew = MsgVonGleichemClient ++ ", Zeitunterschied: " ++ Zeitunterschied,
      werkzeug:logging(Datei, MsgNew ++ "n");
    true ->
      werkzeug:logging(Datei, MsgVonGleichemClient ++ "n")
  end.

msgVonGleichemClient(NNr,Msg,NNummern) ->
    MsgVonGleichemClient = lists:member(NNr, NNummern),
  if
    MsgVonGleichemClient -> Msg ++ "*******";
    true -> Msg
end.

服务器的配置文件:

{sizedlq,400}.
{servername,'serverpa'}.
{cmemtime,2000}.
{hbqname,'hbqpa'}.
{node,'hbqnode'}.
{serverzeit,50}.

客户端的配置文件:

{wartezeit,20}.
{lebenszeit,240}.
{pratikumsgruppe,'2'}.
{teamnummer,'02'}.
{servername,'serverpa'}.
{clientanzahl,5}.
{servernode,'servernode'}.
{cookie,pa}.
{rechner,'rechner'}.

也有分布式的数据分布,这些数据本质上是排队,而且似乎正常工作:

HBQ:

-module(hbq).
-export([startHBQ/0, checkTransfer/6,loophbq/4]).
%%      HBQ !{self(), {request,pushHBQ,[INNr,Msg,TSclientout]}}
startHBQ() ->
  startHBQ("./configs/server.cfg").
%% Used for starting the HBQ with a custom config file

startHBQ(Configfile) ->
        %%Config und Namen auslesen
        Config = loadConfig(Configfile),
    Config = loadConfig(Configfile),
        %%{ok,Config} = file:consult("./config/server.cfg"),
        {ok,HBQName} = werkzeug:get_config_value(hbqname,Config),
        %%Prozess der HBQ starten
        HBQPid = spawn(?MODULE,loophbq,[[],[],Config, 1]),
        %%Prozess registrieren
        register(HBQName,HBQPid),
        HBQPid.

loophbq(HBQ,DLQ,Config,CurrNumber) ->
    receive 
        %%initialisere HBQ und DLQ, sendet ok an Server
        {ServerPid,{request,initHBQ}} ->
            HBQList = [],
            Log = log(Config,["HBQ>>> initialisiert worden von ", ServerPid, ".n"]),
            {ok,DLQSize} = werkzeug:get_config_file(sizedlq,Config),
            DLQ = dlq:initDLQ(DLQSize,Log),
            ServerPid ! {reply,ok},
            loophbq(HBQList, DLQ ,Config, CurrNumber);      
        %%fuegt der Msg einen Zeitstempel hinzu, fuegt sie in HBQ ein, sendet ok
        {ServerPid,{request,pushHBQ,[NNr,Msg,TSclientout]}} ->  
            TShbqin = werkzeug:timeMillliSecond(),
            NewMessage = {NNr,lists:concat(Msg,["HBQ in: ",TShbqin])},
            Log = log(Config,["HBQ>>> Nachricht ",NNr, "in HBQ eingefügt.n"]),
            NewHBQ = [HBQ|NewMessage],
            lists:sort(fun({A,_},{B,_}) -> A=<B end),       
            checkTransfer(NewHBQ, CurrNumber, Config, DLQ,TSclientout,TShbqin),
            ServerPid ! {reply,ok}, 
            loophbq(NewHBQ, DLQ ,Config, CurrNumber);
        %%DLQ soll über HBQ Nachricht an Client senden
        {ServerPid,{request,deliverMSG,NNr,ToClient}} ->
            {ok, HBQName} = werkzeug:get_config_value(hbqname, Config),
            Log = lists:concat(["HB-DLQ@", HBQName, ".log"]),
            Datei = erlang:list_to_atom(Log),
            log(Config, ["HBQ>>> dlq:delivermsg", NNr, pid_to_list(ToClient), "n"]),
            NNrDLQ = dlq:deliverMSG(NNr, ToClient, DLQ, Datei),
            ServerPid ! {reply, NNrDLQ},
            loophbq(HBQ, DLQ ,Config, CurrNumber);
        %%Terminiert Prozess der DLQ
        {ServerPid,{request,delHBQ}} ->
            ServerPid ! {reply,ok},
            ok
      end.

%%CheckTransfer
checkTransfer(HBQ, Number, Config, [DLQ,Size],TSclientout,TShbqin) -> 
    Datei = log(Config, ["HBQ>>> Nachricht Nr ", Number, " wird in DLQ uebertragenn"]),
    FoundMatch = lists:keyfind(Number, 1, HBQ),
    if  FoundMatch =:= false ->
        if(length(HBQ)>Size*0.667) -> 
        [{MinNNr,_}|_] = HBQ,
        %wegen sort ist immer die kleinste NNr vorne in der Liste 
        NewMessage = {MinNNr-1,lists:concat(["Weiß noch nicht was hier reinsoll: ",werkzeug:timeMilliSecond()])},
        NewHBQ = lists:append([{MinNNr-1,NewMessage}], HBQ),
        log(Config,["HBQ>>> Fehlernachricht fuer Nachrichten ",Number," bis",MinNNr-1, " generiert.n"]),
        NewNumber = MinNNr-1,
        checkTransfer(NewHBQ, NewNumber, Config,[DLQ,Size],TSclientout,TShbqin);
        true -> ok
        end;
    true ->
        {MatchNr,Msg} = FoundMatch,
        dlq:push2DLQ([MatchNr, Msg, TSclientout, TShbqin], DLQ, Datei),
        lists:delete(FoundMatch, HBQ),
        checkTransfer(HBQ, Number+1, Config,[DLQ,Size],TSclientout,TShbqin)
end.

log(Config,Message) -> 
    {ok,HBQNode} = werkzeug:get_config_value(node,Config),
    DateiName = lists:concat(["HB-DLQ@", HBQNode,".log"]),
    Datei = erlang:list_to_atom(DateiName),
    werkzeug:logging(Datei, lists:concat(Message)),
    Datei.
%%Dummy-Nachrichten schreiben um Lücken in der HBQ zu füllen wenn sie kritische Größe erreicht
%%Methode um zu prüfen, ob Nachrichten in DLQ geschoben werden können, das dann auch machen
loadConfig(Configfile) ->
  {ok, Config} = file:consult(Configfile),
Config.

dlq:

-module(dlq).
-export([initDLQ/2, delDLQ/1, expectedNr/1, push2DLQ/3, deliverMSG/4]).
%%Initialisiert DLQ mit Kapazitaet Size, Log in Datei
initDLQ(Size, Datei) -> 
werkzeug:logging(Datei,lists:concat(["DLQ>>> intitialisiert worden mit Groesse ",Size,".n"])),
[[],Size].
%%Loescht DLQ
delDLQ(_Queue) -> ok.
%%Liefert NNr die als naechstes in DLQ gespeichert werden kann
%%expectedNr(Queue)
expectedNr([[], _Size]) -> 1;
expectedNr([[[NNr, _Msg, _TSclientout, _TShbqin, _TSdlqin] | _Rest], _Size]) -> NNr + 1.
%%Speichert Nachricht in DLQ, fuegt Zeitstempel hinzu, Rueckgabe: Modifizierte DLQ
%%push2DLQ([NNr, Msg, TSclientout, TShbqin], Queue, Datei)
%%Fehlt noch: Abfrage, ob das die passende Nummer ist!
push2DLQ([NNr, Msg, TSclientout, TShbqin], [DLQ,Size], Datei) ->
  if
    length(DLQ) < Size ->
      werkzeug:logging(Datei, lists:concat(["DLQ>>> Nachricht ", NNr, " in DLQ eingefügt.n"])),
      [[[NNr, Msg, TSclientout, TShbqin, erlang:now()] | DLQ], Size];
    length(DLQ) =:= Size ->
      [LastNNr, _Msg, _TSclientout, _TShbqin, _TSdlqin] = lists:last(DLQ),
      werkzeug:logging(Datei, lists:concat(["DLQ>>> Nachricht ", LastNNr, " aus DLQ entfernt.n"])),
      werkzeug:logging(Datei, lists:concat(["DLQ>>> Nachricht ", NNr, " in DLQ eingefügt.n"])),
      [[[NNr, Msg, TSclientout, TShbqin, erlang:now()] | lists:droplast(DLQ)], Size]
end.
%%Sendet Nachricht an Leser-Client
deliverMSG(MSGNr, ClientPID, Queue, Datei) ->
  %%Aendern: MSGNer = -1, flag am Ende der Reply (siehe zeile 42)
    [{NewestNr,Msg}|Rest] = Queue,
    if MSGNr > NewestNr ->
           DummyMessage = {-1,lists:concat(["DLQ in: ",werkzeug:timeMilliSecond()])}, %% -1 Flag
            werkzeug:logging(Datei, lists:concat(["DLQ>>> DummyNachricht fuer ",MSGNr," an Client ",ClientPID, " ausgeliefert.n"])),
            ClientPID ! {reply,Msg,true}
    end,    
%%%%%%Ab hier noch aendern bzgl Flag
        FoundMatch = lists:keyfind(MSGNr, 1, Queue),
        if
          FoundMatch =:= false -> 
            deliverMSG(MSGNr+1, ClientPID, Queue, Datei),
         if 
       MSGNr =:= NewestNr ->
            {Number,Msg} = FoundMatch,
            NewMessage = {Number,lists:concat(Msg,["DLQ in: ",werkzeug:timeMilliSecond()],-1)},
            werkzeug:logging(Datei, lists:concat(["DLQ>>> Nachricht ", Number, " an Client ",ClientPID, " ausgeliefert.n"])),
            ClientPID ! {reply,Msg,false};
        true ->
        {Number,Msg} = FoundMatch,
            NewMessage = {Number,lists:concat(Msg,["DLQ in: ",werkzeug:timeMilliSecond()],0)},
            werkzeug:logging(Datei, lists:concat(["DLQ>>> Nachricht ", Number, " an Client ",ClientPID, " ausgeliefert.n"])),
            ClientPID ! {reply,Msg,false}
         end;
     true ->
        ok
        end.

cmem:

-module(cmem).
-export([initCMEM/2, delCMEM/1, updateClient/4, getClientNNr/2]).
-import(werkzeug, [get_config_value/2,lengthSL/1,logging/2,reset_timer/3,get_config_value/2,getUTC/0]).
%%Initialisiert CMEM
initCMEM(RemTime, Datei) -> werkzeug:logging(Datei, lists:concat(["CMEM>>> initialisiert mit  ", RemTime, " Sekundenn"])),
  [[], RemTime].
%%Loescht CMEM
delCMEM(_CMEM) -> ok.
%%Speichert/aktualisiert Client und NNr im CMEM, 
updateClient([CMEM, RemTime], ClientID, NNr, Datei) -> 
  ClientTS = getUTC(),
  logging(Datei, lists:concat(["CMEM>>> Client ", ClientID, " wird aktualisiert.n"])),
  [lists:keystore(ClientID, 1, CMEM, {ClientID, NNr, ClientTS}), RemTime].
%%Gibt naechste vom Client erwartete NNr zurueck
%%Es wird geprueft ob Client in der Liste steht und dann
%%mit diesem Wissen eine Hilfsfunktion aufgerufen
getClientNNr([CMEM, RemTime], ClientID) ->
  ClientBekannt = lists:keymember(ClientID, 1, CMEM),
  isClientKnown([CMEM, RemTime], ClientID, ClientBekannt).
%%Client ist nicht bekannt: Naechste NNr = 1
isClientKnown(_CMEM, _ClientID, false) -> 1;
%% Der Client ist bekannt.
%%Zeit noch nicht abgelaufen: Gibt naechste Nummer aus
%%Zeit abgelaufen: Naechste NNr = 1
isClientKnown([CMEM, RemTime], ClientID, true) ->
  {ClientID, NNr, ClientTS} = lists:keyfind(ClientID, 1, CMEM),
  RemainingTime = ClientTS + RemTime,
  Now = getUTC(),
  if
    RemainingTime >= Now -> NNr + 1;
    true -> 1
end.

客户端应该与服务器联系,该服务器将其发送给服务器,将其放入数据结构中,这些数据结构将其发送回客户在正确的情况下。问题是,当我编译它们时,启动HBQ,然后是服务器,然后是客户端,我得到

=ERROR REPORT==== 18-Apr-2017::10:25:46 ===
Error in process <0.104.0> with exit value: {distribution_not_started,[{auth,set_cookie,2,[{file,"auth.erl"},{line,119}]},{client,mitServerVerbinden,6,[{file,"client.erl"},{line,42}]}]}

显然,客户端未连接到服务器存在问题。这是我第一次使用Erlang和分布式系统,所以我不知道发生了什么。

将节点和cookie放入配置并告诉系统的组件在此处查看不足吗?

当erlang vm调用其没有名称时,Auth模块将返回错误distribution_not_started。确保启动Erlang时传递-sname-name标志:

erl -sname test

最新更新