I have wriiten a arithmetic snippet using TSUNG-Erlang function but unable to get through it successfully ; getting following error in my TSUNG controller's log ,
TSUNG-Erlang Snippet,
<setdynvars sourcetype="file" fileid="NBILM_testUsers" delimiter=";" order="iter">
<var name="minnum"/>
<var name="maxnum"/>
</setdynvars>
<setdynvars sourcetype="eval"
code='fun({Pid,DynVars})->
{ok,Maxfound}=ts_dynvars:lookup(maxnum,DynVars),
Maxstr = lists:flatten(io_lib:format("~p",[Maxfound])),
{MAX, _} = string:to_integer(Maxstr),
{ok,Minfound}=ts_dynvars:lookup(minnum,DynVars),
Minstr = lists:flatten(io_lib:format("~p",[Minfound])),
{MIN, _} = string:to_integer(Minstr),
{ok,Countern} = ts_dynvars:lookup(counter,DynVars,999),
Counternstr = lists:flatten(io_lib:format("~p",[Countern])),
{Counternum, _} = string:to_integer(Counternstr),
Mnum1 = MAX + Counternum rem ( 2 - 1 ),
Mnum1 end.
'>
<var name="mnum" />
</setdynvars>
Erroneous log events from TSUNG Controller,
=INFO REPORT==== 5-May-2017::11:42:40 ===
ts_client:(5:<0.134.0>) Stop in state think, reason= {badarith,
[{erlang,
'+',
[error,0],
[]},
{erl_eval,
do_apply,6,
[{file,
"erl_eval.erl"},
{line,
669}]},
{erl_eval,
expr,5,
[{file,
"erl_eval.erl"},
{line,
438}]},
{erl_eval,
exprs,5,
[{file,
"erl_eval.erl"},
{line,
122}]},
{ts_client,
handle_next_action,
1,
[{file,
"src/tsung/ts_client.erl"},
{line,
459}]},
{gen_fsm,
handle_msg,
7,
[{file,
"gen_fsm.erl"},
{line,
518}]},
{proc_lib,
init_p_do_apply,
3,
[{file,
"proc_lib.erl"},
{line,
239}]}]}
=ERROR REPORT==== 5-May-2017::11:42:40 ===
** State machine <0.134.0> terminating
** Last message in was {timeout,#Ref<0.0.8.22>,end_thinktime}
** When State == think
** Data == {state_rcv,none,
{{0,0,0,0},0},
undefined,0,10000,"xyz",80,ts_tcp,
{proto_opts,negociate,"/http-bind/",false,"/chat",
"binary",10,3,600000,infinity,infinity,32768,32768,
undefined,undefined,[],false,true},
false,1,undefined,true,undefined,
{1493,964755,255814},
18,18,false,undefined,0,[],<<>>,
{http,0,0,-1,
{none,none},
false,false,
{false,false},
[],"tsung",[]},
0,1,524288,524288,
[{tsung_userid,1}],
ts_http,[],undefined,full}
Reason for termination =
{badarith,[{erlang,'+',[error,0],[]},
{erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,669}]},
{erl_eval,expr,5,[{file,"erl_eval.erl"},{line,438}]},
{erl_eval,exprs,5,[{file,"erl_eval.erl"},{line,122}]},
{ts_client,handle_next_action,1,
[{file,"src/tsung/ts_client.erl"},{line,459}]},
{gen_fsm,handle_msg,7,[{file,"gen_fsm.erl"},{line,518}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,239}]}]}
It would be really helpful, if someone can point what am doing incorrectly.
The message says that in the line Mnum1 = MAX + Counternum rem ( 2 - 1 ), you are trying to add error with 0 (by the way Counternum rem ( 2 - 1 ) is always equal to 0 so there must be an error here).
Max is the result of {MAX, _} = string:to_integer(Maxstr),, it is equal to error if Maxstr is not a string starting by an integer:
"123" will return {123,[]}
"123 ab" will return {123," ab"}
"a123" will return {error,no_integer}
an_atom will return {error,not_a_list}
To debug further verify the value of Maxfound and Maxstr
you can also shorten your code using the function io:fread/2 which will directly return an integer.
I'm writing a client/server System in Erlang and can't get them to connect. The nodes they should use are stored in config files, which are loaded upon starting them. They also use several distributed data structures. Problem is, I'm first starting the data structure, then the server (works fine) but when I start the client, it doesn't connect to anything and throws an exception.
Server:
-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.
Client:
-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.
Config file for server:
{sizedlq,400}.
{servername,'serverpa'}.
{cmemtime,2000}.
{hbqname,'hbqpa'}.
{node,'hbqnode'}.
{serverzeit,50}.
Config file for client:
{wartezeit,20}.
{lebenszeit,240}.
{pratikumsgruppe,'2'}.
{teamnummer,'02'}.
{servername,'serverpa'}.
{clientanzahl,5}.
{servernode,'servernode'}.
{cookie,pa}.
{rechner,'rechner'}.
There are also distributed data strutures which are essentially queues and seem to be working fine:
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 uebertragen\n"]),
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, " Sekunden\n"])),
[[], 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.
The client is supposed to contact the server sending it a message, the server puts it in data structures which send it back to the client under the right circumstances.
The problem is, when I compile them, the start the HBQ, then the server and then the client, I get
=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}]}]}
So apparently there is an issue with the client not connecting to the server. This is my first time working with Erlang and distributed systems, so I have no idea what is going on.
Is it not enough to put the nodes and cookie into the configs and tell the components of the system to look there?
The error distribution_not_started is returned by the auth module when the erlang VM calling it does not have a name. Ensure that a -sname or -name flag is passed when starting erlang e.g.:
erl -sname test
How can I send a message from paho java client to paho javascript client.
String topic = "chatWith/904";
String content = "Message from MqttPublishSample";
int qos = 0;
String broker = "tcp://127.0.0.1:1883";
String clientId = "JavaSample";
MemoryPersistence persistence = new MemoryPersistence();
try {
MqttClient sampleClient = new MqttClient(broker, clientId, persistence);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setCleanSession(true);
System.out.println("Connecting to broker: "+broker);
sampleClient.connect(connOpts);
System.out.println("Connected");
System.out.println("Publishing message: "+content);
MqttMessage message = new MqttMessage(content.getBytes());
message.setQos(qos);
sampleClient.publish(topic, message);
System.out.println("Message published");
sampleClient.disconnect();
System.out.println("Disconnected");
System.exit(0);
} catch(MqttException me) {
me.printStackTrace();
}
Message exchange between two JS client is happening. But between Javasript & java client, message exchange is not happening.
Here is JS code
client = new Messaging.Client(host, Number(port), clientId);
client.onConnect = onConnect;
client.onMessageArrived = onMessageArrived;
client.onMessageDelivered = onMessageDelivered;
client.onConnectionLost = onConnectionLost;
var willMessage = createByteMessage({
id: '',
'msgType':'USER_STATUS',
'status': 'Offline',
'senderId': myUserId,
'senderName': myName
}, statusTopic);
willMessage.retained = true;
client.connect({
userName:user,
password:password,
onSuccess:onConnect,
onFailure:onFailure,
'willMessage': willMessage
});
Here port is 8083 and mqtt broker is emqtt
client.config
testclientid0
testclientid1 127.0.0.1
testclientid2 192.168.0.1/24
emqttd.config
% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
%% ex: ft=erlang ts=4 sw=4 et
[{kernel, [
{start_timer, true},
{start_pg2, true}
]},
{sasl, [
{sasl_error_logger, {file, "log/emqttd_sasl.log"}}
]},
{ssl, [
%{versions, ['tlsv1.2', 'tlsv1.1']}
]},
{lager, [
{colored, true},
{async_threshold, 5000},
{error_logger_redirect, false},
{crash_log, "log/emqttd_crash.log"},
{handlers, [
%%{lager_console_backend, info},
%%NOTICE: Level >= error
%%{lager_emqtt_backend, error},
{lager_file_backend, [
{formatter_config, [time, " ", pid, " [",severity,"] ", message, "\n"]},
{file, "log/emqttd_error.log"},
{level, error},
{size, 104857600},
{date, "$D0"},
{count, 30}
]}
]}
]},
{esockd, [
{logger, {lager, error}}
]},
{emqttd, [
%% Authentication and Authorization
{access, [
%% Authetication. Anonymous Default
{auth, [
%% Authentication with username, password
%{username, []},
%% Authentication with clientid
%{clientid, [{password, no}, {file, "etc/clients.config"}]},
%% Authentication with LDAP
% {ldap, [
% {servers, ["localhost"]},
% {port, 389},
% {timeout, 30},
% {user_dn, "uid=$u,ou=People,dc=example,dc=com"},
% {ssl, fasle},
% {sslopts, [
% {"certfile", "ssl.crt"},
% {"keyfile", "ssl.key"}]}
% ]},
%% Allow all
{anonymous, []}
]},
%% ACL config
{acl, [
%% Internal ACL module
{internal, [{file, "etc/acl.config"}, {nomatch, allow}]}
]}
]},
%% MQTT Protocol Options
{mqtt, [
%% Packet
{packet, [
%% Max ClientId Length Allowed
{max_clientid_len, 512},
%% Max Packet Size Allowed, 64K default
{max_packet_size, 65536}
]},
%% Client
{client, [
%% Socket is connected, but no 'CONNECT' packet received
{idle_timeout, 30} %% seconds
]},
%% Session
{session, [
%% Max number of QoS 1 and 2 messages that can be “in flight” at one time.
%% 0 means no limit
{max_inflight, 100},
%% Retry interval for redelivering QoS1/2 messages.
{unack_retry_interval, 60},
%% Awaiting PUBREL Timeout
{await_rel_timeout, 20},
%% Max Packets that Awaiting PUBREL, 0 means no limit
{max_awaiting_rel, 0},
%% Statistics Collection Interval(seconds)
{collect_interval, 0},
%% Expired after 2 day (unit: minute)
{expired_after, 2880}
]},
%% Queue
{queue, [
%% simple | priority
{type, simple},
%% Topic Priority: 0~255, Default is 0
%% {priority, [{"topic/1", 10}, {"topic/2", 8}]},
%% Max queue length. Enqueued messages when persistent client disconnected,
%% or inflight window is full.
{max_length, infinity},
%% Low-water mark of queued messages
{low_watermark, 0.2},
%% High-water mark of queued messages
{high_watermark, 0.6},
%% Queue Qos0 messages?
{queue_qos0, true}
]}
]},
%% Broker Options
{broker, [
%% System interval of publishing broker $SYS messages
{sys_interval, 60},
%% Retained messages
{retained, [
%% Expired after seconds, never expired if 0
{expired_after, 0},
%% Max number of retained messages
{max_message_num, 100000},
%% Max Payload Size of retained message
{max_playload_size, 65536}
]},
%% PubSub and Router
{pubsub, [
%% Default should be scheduler numbers
{pool_size, 8},
%% Store Subscription: true | false
{subscription, true},
%% Route aging time(seconds)
{route_aging, 5}
]},
%% Bridge
{bridge, [
%%TODO: bridge queue size
{max_queue_len, 10000},
%% Ping Interval of bridge node
{ping_down_interval, 1} %seconds
]}
]},
%% Modules
{modules, [
%% Client presence management module.
%% Publish messages when client connected or disconnected
{presence, [{qos, 0}]},
%% Subscribe topics automatically when client connected
{subscription, [
%% $c will be replaced by clientid
%% {"$queue/clients/$c", 1},
%% Static subscriptions from backend
backend
]}
%% Rewrite rules
%% {rewrite, [{file, "etc/rewrite.config"}]}
]},
%% Plugins
{plugins, [
%% Plugin App Library Dir
{plugins_dir, "./plugins"},
%% File to store loaded plugin names.
{loaded_file, "./data/loaded_plugins"}
]},
%% Listeners
{listeners, [
{mqtt, 1883, [
%% Size of acceptor pool
{acceptors, 16},
%% Maximum number of concurrent clients
{max_clients, 512},
%% Socket Access Control
{access, [{allow, all}]},
%% Connection Options
{connopts, [
%% Rate Limit. Format is 'burst, rate', Unit is KB/Sec
%% {rate_limit, "100,10"} %% 100K burst, 10K rate
]},
%% Socket Options
{sockopts, [
%Set buffer if hight thoughtput
%{recbuf, 4096},
%{sndbuf, 4096},
%{buffer, 4096},
%{nodelay, true},
{backlog, 1024}
]}
]},
{mqtts, 8883, [
%% Size of acceptor pool
{acceptors, 4},
%% Maximum number of concurrent clients
{max_clients, 512},
%% Socket Access Control
{access, [{allow, all}]},
%% SSL certificate and key files
{ssl, [{certfile, "etc/ssl/ssl.crt"},
{keyfile, "etc/ssl/ssl.key"}]},
%% Socket Options
{sockopts, [
{backlog, 1024}
%{buffer, 4096},
]}
]},
%% WebSocket over HTTPS Listener
%% {https, 8083, [
%% %% Size of acceptor pool
%% {acceptors, 4},
%% %% Maximum number of concurrent clients
%% {max_clients, 512},
%% %% Socket Access Control
%% {access, [{allow, all}]},
%% %% SSL certificate and key files
%% {ssl, [{certfile, "etc/ssl/ssl.crt"},
%% {keyfile, "etc/ssl/ssl.key"}]},
%% %% Socket Options
%% {sockopts, [
%% %{buffer, 4096},
%% {backlog, 1024}
%% ]}
%%]},
%% HTTP and WebSocket Listener
{http, 8083, [
%% Size of acceptor pool
{acceptors, 4},
%% Maximum number of concurrent clients
{max_clients, 64},
%% Socket Access Control
{access, [{allow, all}]},
%% Socket Options
{sockopts, [
{backlog, 1024}
%{buffer, 4096},
]}
]}
]},
%% Erlang System Monitor
{sysmon, [
%% Long GC, don't monitor in production mode for:
%% https://github.com/erlang/otp/blob/feb45017da36be78d4c5784d758ede619fa7bfd3/erts/emulator/beam/erl_gc.c#L421
{long_gc, false},
%% Long Schedule(ms)
{long_schedule, 240},
%% 8M words. 32MB on 32-bit VM, 64MB on 64-bit VM.
%% 8 * 1024 * 1024
{large_heap, 8388608},
%% Busy Port
{busy_port, false},
%% Busy Dist Port
{busy_dist_port, true}
]}
]}
].