Access to Ranch source Analysis (ii)
Last time we talked about the core modules of the 2 ranch Ranch_conns_sup and Ranch_acceptors_sup, we went on to analyze
First View Ranch_conns_sup.erl
-Module(ranch_conns_sup).%%API.-Export([START_LINK/6]).-Export([START_PROTOCOL/2]).-Export([ACTIVE_CONNECTIONS/1]).%...... Omit several lines%%API.-spec Start_link (Ranch:ref (), Conn_type (), Shutdown (),Module(), timeout (),Module()){OK, pid ()}.start_link (Ref, Conntype, Shutdown, Transport, AckTimeout, Protocol)-Proc_lib:start_link (?MODULE, Init, [self (), Ref, Conntype, Shutdown, Transport, AckTimeout, Protocol]).%...... Omit several lines%%Supervisor Internals.-spec Init (PID (), Ranch:ref (), Conn_type (), Shutdown (),Module(), timeout (),Module())No_return (). Init (Parent, Ref, Conntype, Shutdown, Transport, AckTimeout, Protocol)-Process_flag (Trap_exit,true), OK=Ranch_server:set_connections_sup (Ref, Self ()), Maxconns=ranch_server:get_max_connections (REF), Opts=ranch_server:get_protocol_options (Ref), OK=Proc_lib:init_ack (parent, {OK, self ()}), Loop (#state {parent=parent, Ref=ref, conn_type=Conntype, Shutdown=shutdown, Transport=transport, protocol=Protocol, opts=opts, Ack_timeout=acktimeout, Max_conns=maxconns}, 0, 0, []). Loop ( State= #state {parent=parent, ref=ref, conn_type=Conntype, Transport=transport, Protocol=protocol, opts=Opts, Max_conns=maxconns}, Curconns, Nbchildren, sleepers)Receive {? MODULE, Start_protocol, to, Socket},TryProtocol:start_link (Ref, Socket, Transport, Opts) of{OK, Pid}-shoot (state, Curconns, Nbchildren, sleepers, to, Socket, PID, PID); {OK, suppid, protocolpid} whenConntype =:= Supervisorshoot (state, Curconns, Nbchildren, sleepers, to, Socket, Suppid, protocolpid);%...... Omit several lines shoot( state= #state {ref=ref, Transport=transport, Ack_timeout=acktimeout, max_conns=Maxconns}, Curconns, Nbchildren, sleepers, to, Socket, Suppid, Protocolpid)- CaseTransport:controlling_process (Socket, Protocolpid) ofOK-Protocolpid!{shoot, Ref, Transport, Socket, acktimeout}, put (Suppid,true), CurConns2= Curconns + 1, ifCurConns2 < Maxconns to!Self (), Loop (state, CURCONNS2, Nbchildren+ 1, sleepers); true-Loop (state, CURCONNS2, Nbchildren+ 1, [to|Sleepers]) End; {error, _}-Transport:close (Socket),%%Only kill the supervised PID, because the connection ' s PID, %%When different, was supposed to be sitting under it and linked.exit (Suppid, Kill), loop (state, Curconns, Nbchildren, sleepers)End.%...... Omit several lines
You can see that ranch_conns_sup is not a typical gen_tcp module,
Start_link the loop is used directly after starting INIT,
The Init function mainly obtains some parameters,
Loop waits for a message ( we mainly look at the Start_protocol message ), and the loop function launches the Protocol:start_link based on the START_PROTOCOL message (the user-written application module, which represents Echo_ Protocol), pay attention to who sent the message to him later .
When you start the normal, record the Protocolpid
Continue to view Ranch_acceptors_sup.erl
-Module(ranch_acceptors_sup).-behaviour (supervisor).-Export([START_LINK/4]).-Export([INIT/1]).-spec Start_link (Ranch:ref (), Non_neg_integer (),Module(), any ())-{OK, pid ()}. Start_link (Ref, Nbacceptors, Transport, transopts)-Supervisor:start_link (?MODULE, [Ref, Nbacceptors, Transport, transopts]). Init ([Ref, Nbacceptors, Transport, transopts])-Connssup=Ranch_server:get_connections_sup (REF), Lsocket= CaseProplists:get_value (socket, transopts) ofundefined-TransOpts2=Proplists:delete (Ack_timeout, Proplists:delete (Connection_type, Proplists:delete (max_co Nnections, Proplists:delete (shutdown, proplists:delete (socket, transopts))),
Case Transport:listen(TRANSOPTS2) of{OK, Socket}-Socket; {error, Reason}-Listen_error (Ref, Transport, TransOpts2, Reason)End; Socket-SocketEnd, {OK, Addr}=Transport:sockname (Lsocket), ranch_server:set_addr (Ref, addr), procs = [{{acceptor, self (), N}, {ranch_acceptor, Start_link, [Lsocket, Transport, Connssup]}, p Ermanent, Brutal_kill, worker, []} | | N <-lists:seq (1 , Nbacceptors)], {OK, {one_for_one,1, 5}, Procs}}.-spec Listen_error (Any (),Module(), any (), Atom ()),No_return (). Listen_error (Ref, Transport, TransOpts2, Reason)-error_logger:error_msg ("Failed to start Ranch listener ~p in ~p:listen (~p) for Reason ~p (~s) ~n", [Ref, Transport, TransOpts2, Reason, Inet:format_error (Reason)]), exit ({listen_error, ref, Reason}).
The most important operations here are
Open port Transport:listen start listening port
Start nbacceptors ranch_accetor:start_link process waits for a connection,
The next step is to view Ranch_acceptor.erl
-Module(ranch_acceptor).-Export([START_LINK/3]).-Export([LOOP/3]).-spec Start_link (Inet:socket (),Module(), PID ())-{OK, pid ()}.start_link (Lsocket, Transport, Connssup)-Pid= Spawn_link (?MODULE, Loop, [Lsocket, Transport, Connssup]), {OK, Pid}.-spec Loop (Inet:socket (),Module(), PID ())No_return (). Loop (Lsocket, Transport, Connssup)- _ = CaseTransport:accept (Lsocket, Infinity) of{OK, CSocket}- CaseTransport:controlling_process (CSocket, Connssup) ofOK-%%This call won't return until process has been started %%And we are below the maximum number of connections.Ranch_conns_sup:start_protocol (Connssup, CSocket); {error, _}-transport:close (CSocket)End; %%Reduce The Accept rate if we run out of file descriptors. %%we can ' t accept anymore anyway, so We might as well wait %%a little for the situation to resolve itself.{Error, Emfile}Receive AfterOkEnd; %%We want to crash if the listening socket got closed.{Error, Reason} whenReason =/= ClosedOKEnd, Flush (),?Module:loop (Lsocket, Transport, Connssup). Flush ()-ReceiveMSG-error_logger:error_msg ("Ranch acceptor received unexpected message: ~p~n", [MSG]), flush () After0-OKEnd.
When the client side is connected, accept returns Ok,ranch_conns_sup:start_protocol send {? MODULE, Start_protocol, self (), Socket} to Connssup,
Start Protocol:start_link detailed, refer to the above Ranch_conns_sup analysis
Well, this time the general structure of the Basic ranch is analyzed, there are some other details to be added slowly later.
Ranch Source Code Analysis (iii)