gen_server, gen_tcp question

Eric Merritt <>
Wed Jul 17 15:59:14 CEST 2002


Kent,

 Thanks allot this actually clears things up quite a
bit. I do have one question though, the rshell app you
mention does not seem to be in my erlang distro
(R8-1). Do you have any idea where I could get it
from? or do I need to recompile erlang with some
options set?

Thanks,
Eric
--- Kent Boortz <> wrote:
> 
> Eric Merritt <> writes:
> >  As some of you may know I am fairly new to
> erlang. I
> > have been poking around a bit getting my feet wet,
> > messing with yaws, mnesia, etc. Well I am finally
> > getting around to coding a fairly heft application
> as
> > a learning exercise and I have hit a stumbling
> block.
> > I am just begining to write the tcp comm part of
> the
> > application, I would love to follow the otp
> practices
> > and make use of gen_server. There even seems to be
> > some arcane way for gen_tcp and gen_server to work
> > together for a module. I can't, for the life of
> me,
> > figure it out. The documentation is pretty sparse
> in
> > this area as well. 
> 
> If you talk about creating an application that
> listen to a port and
> accept an connection then I think they don't fit
> together as well as
> they should do. Some OTP applications bypass the
> gen_server module and
> use the sys module to use gen_tcp and still fit into
> the supervision
> model of Erlang/OTP. You can look at the source of
> ssl or the P9
> rshell application for an example of this. There is
> an ascii drawing
> in "$ERL_TOP/lib/rshell/src/rshell.erl" that show
> the supervisor
> structure.
> 
> One problem is that we can't sit and wait for a
> connection in the
> blocking call gen_tcp:accept() because the
> application may get a code
> change system message. One way around this is to
> give a timeout of one
> second to gen_tcp:accept() to leave the call and
> pick up system
> messages if any and redo the accept call.
> 
> A second problem that gen_tcp solves in an unusual
> way (a bit ugly in
> my opinion) is that after an accept of a connection
> in active mode
> messages with TCP data may be received to the
> message queue of the
> process calling gen_tcp:accept() before it has
> started a process to
> handle the specific connection. There is a function
> gen_tcp:controlling_process() that redirect these
> messages to a new
> process and, from what I have been told, actually
> move the TCP
> messages from the message queue of the first process
> to the new
> controlling process,
> 
> kent
> 
> 
> init(Parent, Options) ->
>     process_flag(trap_exit, true),
> 
>     Deb = sys:debug_options(?DBG_OPTS ++ Options),
>     Port = get_port(Options),
>     AcceptTimeout =
>         case application:get_env(rshell,
> accept_timeout) of
>             {ok, AcceptT} ->
>                 AcceptT;
>             undefined ->
>                 1000                            %
> XXX: Create a macro!!!
>         end,
> 
>     Opts =
>         [
>          {nodelay, true},
>          {packet,raw},
>          {reuseaddr,true}
>         ],
> 
>     % We crash if we can't open the socket to listen
>     {ok, ListenSocket} = gen_tcp:listen(Port, Opts),
> 
>     loop(Parent, Deb, ListenSocket, AcceptTimeout).
> 
> 
> loop(Parent, Deb, ListenSocket, AcceptTimeout) ->
>     receive
>         {system, From, Request} ->
>             State = {ListenSocket, AcceptTimeout},
>             sys:handle_system_msg(Request, From,
> Parent, ?MODULE, Deb, State);
>         What ->
>             NewDeb = sys:handle_debug(Deb, {?MODULE,
> write_debug}, rshell_listener,
>                                       {in, What}),
>             loop(Parent, NewDeb, ListenSocket,
> AcceptTimeout)
>             case gen_tcp:accept(ListenSocket,
> AcceptTimeout) of
>                 {ok, Sock} ->
>                     case
> supervisor:start_child(rshell_connection_sup,
>                                                
> [Sock]) of
>                         {ok,Pid} when pid(Pid) ->
>                            
> gen_tcp:controlling_process(Sock, Pid),
>                             loop(Parent, Deb,
> ListenSocket, AcceptTimeout);
>                         Other ->
>                             NewDeb =
> sys:handle_debug(Deb,
>                                                     
>  {?MODULE, write_debug},
>                                                     
>  rshell_listener,
>                                                     
>  {start_child_result,
>                                                     
>   Other}),
>                             gen_tcp:close(Sock),
>                             loop(Parent, NewDeb,
> ListenSocket, AcceptTimeout)
>                     end;
>                 {error, timeout} ->
>                     %% This is what we want to
> enable system events
>                     loop(Parent, Deb, ListenSocket,
> AcceptTimeout);
>                 Other ->
>                     NewDeb = sys:handle_debug(Deb,
>                                              
> {?MODULE, write_debug},
>                                              
> rshell_listener,
>                                              
> {accept_result,Other}),
>                     loop(Parent, NewDeb,
> ListenSocket, AcceptTimeout)
>             end
>     end.


__________________________________________________
Do You Yahoo!?
Yahoo! Autos - Get free new car price quotes
http://autos.yahoo.com



More information about the erlang-questions mailing list