Using TCP sockets with 'receive' instead 'gen_tcp:recv/2'

Jérémie Lumbroso <>
Sun Mar 26 16:01:17 CEST 2006


Hello,

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
Clue[do] server. But I've encountered a serious problem with the receive ...
after ... end construct. I would like to use it to handle the client sockets
which were obtained using gen_tcp:accept/1, and for that purpose, have made
sure to set the option {active, true} wherever I thought it mattered. But it
still does not work—and I have no idea why.

This is the code that I use to create the listening socket:

gen_tcp:listen(?port, [binary,
                       {nodelay, true},
                       {packet, 0},
                       {reuseaddr, true},
                       {active, false}])


And here is how I accept the client sockets:

server_accept(LSock, User_List) ->
    case gen_tcp:accept(LSock, 1000) of

        %%%%
        % Spawning a new thread, linking to it, and returning
        % a new 'user list'.
        {ok, Sock} ->
            io:format("Client connected successfully ...~n"),
            Pid = spawn_link(?MODULE, relay, [Sock]),
            Client = #client{pid = Pid, socket = Sock},
            [ Client | User_List ];

        _Else ->
            User_List
    end.

And finally, here is the relay function in question (BTW, the documentation
says that I can't use the receive to figure out when a socket created with
accept is closed, but I was not sure if this was an omission or an actual
limitation):

relay(Socket) ->
    io:format("[debug]-> start~n"),
    %%%% Activate socket (so we can receive through it.
    inet:setopts(Socket, [binary, {nodelay,true},
                          {active, true}]),
    relay(Socket, []).

relay(Socket, Buffer) ->
    receive

        %%%%
        % Split the received data in lines, process them
        % and put the extra data back in buffer before
        % starting the loop again.
        {tcp, Socket, Bin} ->
            Data = binary_to_list(Bin),
            io:format("[debug]-> ~p~n", [ Data ]),
            case regexp:split(Buffer ++ Data, "\r\n") of
                {ok, FieldList} ->
                    New_Buffer = process_lines(FieldList);

                _NoMatch ->
                    New_Buffer = Buffer ++ Data
            end,
            ?MODULE:relay(Socket, New_Buffer);

        {tcp_closed, Socket} ->
            io:format("[debug]-> end"),
            exit(self(), tcp_closed);

        {server, close} ->
            gen_tcp:close(Socket),
            exit(self(), tcp_closed);

        {server, {data, Data}} ->
            gen_tcp:send(Socket, Data),
            ?MODULE:relay(Socket, Buffer)

        after
            5000 ->
                io:format("[debug]-> wait~n"),
                ?MODULE:relay(Socket, Buffer)
    end.

In case this is not enough, I've attached the whole file as well.

Is there something that I'm doing wrong or is this just how it (doesn't)
work?

Best Regards,

- Jérémie Lumbroso
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20060326/2b17f0b6/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: snippet.erl
Type: application/octet-stream
Size: 3428 bytes
Desc: not available
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20060326/2b17f0b6/attachment.obj>


More information about the erlang-questions mailing list