[erlang-questions] %5Berlang-questions%5D%20Questions%20on%20gen_tcp%20%26%20flexible%20parsing%20-2-%0A%09%28readable&In-Reply-To=386001.61120.qm%40web51107.mail.re2.yahoo.com
Bo
kosmyq@REDACTED
Fri Apr 4 01:15:34 CEST 2008
Code examples for my questions:
Simplified Socket Server, taken from
http://www.erlang.org/doc/man/gen_tcp.html and modified
for auto updates:
-module(test).
-compile(export_all).
start() ->
spawn(?MODULE, start1, [3,5678]).
start1(Num,Port) ->
register(?MODULE, self()),
start(Num,Port),
sloop([]).
sloop(Ls) ->
receive
{accept, Pid} ->
sloop([Pid|Ls]);
upgrade ->
io:format("TEST: Loop upgrading.~n"),
lists:foreach(fun(Pid) ->
Pid ! upgrade,
io:format("TEST: Loop .. upgrading ..~p..~n",[Pid])
end, Ls),
?MODULE:sloop(Ls);
quit ->
io:format("Loop quitting~n"),
sloop(Ls);
Other ->
io:format("Loop other: ~p~n",[Other]),
sloop(Ls)
end.
start(Num,LPort) ->
case gen_tcp:listen(LPort,[{active, false},{packet,2}]) of
{ok, ListenSock} ->
start_servers(Num,ListenSock),
{ok, Port} = inet:port(ListenSock),
Port;
{error,Reason} ->
{error,Reason}
end.
start_servers(0,_) ->
ok;
start_servers(Num,LS) ->
Pid=spawn(?MODULE,server,[LS]),
?MODULE ! {accept, Pid},
start_servers(Num-1,LS).
server(LS) ->
case gen_tcp:accept(LS) of
{ok,S} ->
loop(S),
?MODULE:start_servers(1,LS);
upgrade ->
io:format("TEST: ACPT upgrading ~p~n", [self()]),
?MODULE:server(LS);
Other ->
io:format("accept returned ~w - goodbye!~n",[Other]),
ok
end,
receive
upgrade ->
io:format("TEST: ACPT2 upgrading ~p~n", [self()]),
?MODULE:server(LS);
Other1 ->
io:format("accept returned ~w - goodbye!~n",[Other1]),
server(LS)
end.
loop(S) ->
inet:setopts(S,[{active,once}]),
receive
{tcp,S,Data} ->
Answer = process(Data),
gen_tcp:send(S,Answer),
loop(S);
{tcp_closed,S} ->
io:format("Socket ~w closed [~w]~n",[S,self()]),
ok;
upgrade ->
io:format("TEST: Client upgrading ~p~n", [self()]),
?MODULE:loop(S)
end.
process(Data) -> Data.
******************************
The original code has a flaw in that if you type in
something erroneous in the shell and your program will
terminate, because the socket responds to errors in the
controlling process, which by default is whoever created it,
so I modified the code so that the program spawns a loop
function (the controlling process) and stays there, hence
errors in the shell no longer affect it.
Problem: when sending a "test ! upgrade." the instruction
"gen_tcp:accept(LS)" does NOT receive the update and
hence the 2nd update fails and terminates the code. How
can I make this work ??
*******************************************************************
Parser questions:
This example should work now:
parsecmd(T) ->
parsecmd(T, []).
parsecmd("{USR:" ++ T, L) ->
{Url, T1} = collect_usr(T, reverse("")),
parsecmd(T1, [Url|L]);
parsecmd([_|T], L) ->
parsecmd(T, L);
parsecmd([], L) ->
L.
collect_usr("}" ++ T, L) -> {reverse(L, ""), T};
collect_usr([H|T], L) -> collect_usr(T, [H|L]);
collect_usr([], _) -> {[],[]}.
*******************************************************************
What does not work is this:
parsecmd(Cmd, T) ->
parsecmd(Cmd, T, []).
parsecmd(Cmd ++ T, L) ->
{Url, T1} = collect_usr(T, reverse("")),
parsecmd(T1, [Url|L]);
.......
One cannot insert a variable Cmd in this case to make this search more flexible, Erlang complains about it. The statement to be evaluated MUST be a fixed one, which is not so nice, so "parsecmd(Cmd ++ T, L) ->" will not work,
"parsecmd("{USR:" ++ T, L) ->" will, but the term is fixed, I would like it to be variable.
I hope this clarifies my doubts a bit.
Thanks,
Bo
---------------------------------
You rock. That's why Blockbuster's offering you one month of Blockbuster Total Access, No Cost.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080403/2d60fc27/attachment.htm>
More information about the erlang-questions
mailing list