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

orbitz <>
Sun Mar 26 19:03:58 CEST 2006


You need to set the sockets controling proces to the new one you  
spawn.  How is the socket supposed to know who to send its messages  
to after all?

On Mar 26, 2006, at 9:01 AM, Jérémie Lumbroso wrote:

> 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
>
>
>
>
>
>
> <snippet.erl>




More information about the erlang-questions mailing list