[erlang-questions] gen_tcp:recv and hairloss
Kevin
q2h46uw02@REDACTED
Sat Nov 8 05:20:21 CET 2008
I'm having a hell of a time with gen_tcp:recv
here are the options I use for gen_tcp:listen
-define(TCP_OPTS, [binary, {packet, raw}, {active, false}, {reuseaddr,
true}]).
So the idea is all the listening and accept stuff is handled
successfully at the top of a gen_server.
Here's a simplified idea at the gen_server level, (there's some
conditional handling that gets confusing so I took it out)
loop(Sock, Fsm) ->
case gen_tcp:recv(Sock, 0, ?RECV_TIMEOUT) of
{ok, Request} ->
ok = gen_fsm:send_event(Fsm, {Request, Sock}),
loop(Sock, Fsm)
{error, Reason} ->
dont_worry_bout_it
end.
There might be a typo from the editing for this email, but this, so far,
has worked great.
Now in the Fsm, I examine the Request binary, have some fun with it,
then use gen_tcp:send(Sock, Msg)
to reply. This all works great, and I've hammered it and it takes a
good load.
So to recap, the gen server loops over the input, usually telnet for
....ing purposes, and passes each line
to the Fsm, which then replies.
I decided I wanted a tighter loop inside the Fsm, so I reproduced the
same loop there, given the same socket,
and I get the error "ealready", which means something like "operation
already in progress".
Basically I can't read from the socket unless I come back up out of the
Fsm and let the same loop get the next line. What is so
special about the gen_server process that can *read* from the socket and
the fsm process that cant?!?
I tried to reproduce the problem, and I'm having NO problem. One
difference I can think of is that the recv in the Fsm is in a different
process.
Here is a simplified version that shows no problems. Its an echo server
that goes quiet when you tell it "sssh" in telnet.
start() ->
{ok, LSock} = gen_tcp:listen(5678, [binary, {packet, raw},
{active, false},
{reuseaddr, true}]),
{ok, Sock} = gen_tcp:accept(LSock),
do_recv(Sock),
gen_tcp:close(Sock).
do_recv(Sock) ->
case gen_tcp:recv(Sock, 0) of
{ok, B} ->
case B of
<<"sssh\r\n">> -> %% silent mode
sssh(Sock);
X ->
gen_tcp:send(Sock, X),
do_recv(Sock)
end;
{error, Reason} ->
io:format("Error:~p~n", [Reason])
end.
sssh(Sock) ->
case gen_tcp:recv(Sock, 0) of
{ok, _} ->
sssh(Sock);
{error, Reason} ->
io:format("Error2:~p~n", [Reason])
end.
More information about the erlang-questions
mailing list