Hello,<br><br>To get to know Erlang, and how to use it, I've set myself a small introductory project. So for this first project, I wanted to write a <span style="font-style: italic;">Clue[do]</span> server. But I've encountered a serious problem with the
<span style="font-weight: bold; font-family: courier new,monospace;">receive ... after ... end</span> construct. I would like to use it to handle the client sockets which were obtained using <span style="font-family: courier new,monospace;">
gen_tcp:accept/1</span>, and for that purpose, have made sure to set the option <span style="font-family: courier new,monospace;">{active, true}</span> wherever I thought it mattered. But it still does not work—and I have no idea why.
<br><br>This is the code that I use to create the listening socket:<br><br><div style="margin-left: 40px;"><span style="font-family: courier new,monospace;">gen_tcp:listen(?port, [binary,</span><span style="font-family: courier new,monospace;">
</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> {nodelay, true},</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">
{packet, 0},</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> {reuseaddr, true}, </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> {active, false}])</span><br></div><br><br>And here is how I accept the client sockets:<br><br><div style="margin-left: 40px;"><span style="font-family: courier new,monospace;">
server_accept(LSock, User_List) -></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> case gen_tcp:accept(LSock, 1000) of</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> %%%%</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> % Spawning a new thread, linking to it, and returning</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> % a new 'user list'.
</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> {ok, Sock} -></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">
io:format("Client connected successfully ...~n"),</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> Pid = spawn_link(?MODULE, relay, [Sock]),
</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> Client = #client{pid = Pid, socket = Sock},</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">
[ Client | User_List ];</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">
_Else -></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> User_List</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">
end.</span><br></div><br>And finally, here is the <span style="font-family: courier new,monospace;">relay</span> function in question (BTW, the documentation says that I can't use the receive to figure out when a socket created with
<span style="font-family: courier new,monospace;">accept</span> is closed, but I was not sure if this was an omission or an actual limitation):<br><br><div style="margin-left: 40px;"><span style="font-family: courier new,monospace;">
relay(Socket) -></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> io:format("[debug]-> start~n"),</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> %%%% Activate socket (so we can receive through it.</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> inet:setopts(Socket, [binary, {nodelay,true},
</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> {active, true}]),</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">
relay(Socket, []).</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">relay(Socket, Buffer) -></span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> receive</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> %%%%</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> % Split the received data in lines, process them
</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> % and put the extra data back in buffer before</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">
% starting the loop again.</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> {tcp, Socket, Bin} -></span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> Data = binary_to_list(Bin),</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> io:format("[debug]-> ~p~n", [ Data ]),
</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> case regexp:split(Buffer ++ Data, "\r\n") of</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> {ok, FieldList} -></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> New_Buffer = process_lines(FieldList);
</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">
_NoMatch -></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> New_Buffer = Buffer ++ Data</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> end,</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> ?MODULE:relay(Socket, New_Buffer);</span>
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> {tcp_closed, Socket} ->
</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> io:format("[debug]-> end"),</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">
exit(self(), tcp_closed);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">
{server, close} -></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> gen_tcp:close(Socket),</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> exit(self(), tcp_closed);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> {server, {data, Data}} -></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> gen_tcp:send(Socket, Data),
</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> ?MODULE:relay(Socket, Buffer)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">
</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> after</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">
5000 -></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> io:format("[debug]-> wait~n"),</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> ?MODULE:relay(Socket, Buffer)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> end.</span><br></div>
<br>In case this is not enough, I've attached the whole file as well.<br><br>Is there something that I'm doing wrong or is this just how it (doesn't) work?<br><br>Best Regards,<br><br>- Jérémie Lumbroso<br><br><br><br><br>
<br><br>