zoukankan      html  css  js  c++  java
  • ranch 源码分析(二)

    接上ranch 源码分析(一)

    上次讲到了ranch.erl的start_listener函数,下面我们详细分析下这个函数

    -module(ranch).
    
    %...... 省略若干行
    
    -spec start_listener(ref(), non_neg_integer(), module(), any(), module(), any())
        -> supervisor:startchild_ret().
    start_listener(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts)
            when is_integer(NbAcceptors) andalso is_atom(Transport)
            andalso is_atom(Protocol) ->
        _ = code:ensure_loaded(Transport),
        %% @todo Remove in Ranch 2.0 and simply require ssl.
        _ = ensure_ssl(Transport),
        case erlang:function_exported(Transport, name, 0) of
            false ->
                {error, badarg};
            true ->
                Res = supervisor:start_child(ranch_sup, child_spec(Ref, NbAcceptors,
                        Transport, TransOpts, Protocol, ProtoOpts)),
                Socket = proplists:get_value(socket, TransOpts),
                case Res of
                    {ok, Pid} when Socket =/= undefined ->
                        %% Give ownership of the socket to ranch_acceptors_sup
                        %% to make sure the socket stays open as long as the
                        %% listener is alive. If the socket closes however there
                        %% will be no way to recover because we don't know how
                        %% to open it again.
                        Children = supervisor:which_children(Pid),
                        {_, AcceptorsSup, _, _}
                            = lists:keyfind(ranch_acceptors_sup, 1, Children),
                        %%% Note: the catch is here because SSL crashes when you change
                        %%% the controlling process of a listen socket because of a bug.
                        %%% The bug will be fixed in R16.
                        catch Transport:controlling_process(Socket, AcceptorsSup);
                    _ ->
                        ok
                end,
                Res
        end.
    
    
    %...... 省略若干行
    
    -spec child_spec(ref(), non_neg_integer(), module(), any(), module(), any())
        -> supervisor:child_spec().
    child_spec(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts)
            when is_integer(NbAcceptors) andalso is_atom(Transport)
            andalso is_atom(Protocol) ->
        %% @todo Remove in Ranch 2.0 and simply require ssl.
        _ = ensure_ssl(Transport),
        {{ranch_listener_sup, Ref}, {ranch_listener_sup, start_link, [
            Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts
        ]}, permanent, infinity, supervisor, [ranch_listener_sup]}.
    
    %...... 省略若干行

    可以看到在ranch的start_listener中,首先查看Transport模块(传输层模块,这里是ranch_tcp)是否载入,

    如果正常载入就启动ranch_listener_sup:start_link/6为ranch_sup的子进程

    supervisor:start_child不明白的可以参考 [Erlang 0030] 理解Erlang/OTP Supervisor

     

    下面我们查看ranch_listener_sup.erl

    -module(ranch_listener_sup).
    -behaviour(supervisor).
    
    -export([start_link/6]).
    -export([init/1]).
    
    -spec start_link(ranch:ref(), non_neg_integer(), module(), any(), module(), any())
        -> {ok, pid()}.
    start_link(Ref, NbAcceptors, Transport, TransOpts, Protocol, ProtoOpts) ->
        MaxConns = proplists:get_value(max_connections, TransOpts, 1024),
        ranch_server:set_new_listener_opts(Ref, MaxConns, ProtoOpts),
        supervisor:start_link(?MODULE, {
            Ref, NbAcceptors, Transport, TransOpts, Protocol
        }).
    
    init({Ref, NbAcceptors, Transport, TransOpts, Protocol}) ->
        AckTimeout = proplists:get_value(ack_timeout, TransOpts, 5000),
        ConnType = proplists:get_value(connection_type, TransOpts, worker),
        Shutdown = proplists:get_value(shutdown, TransOpts, 5000),
        ChildSpecs = [
            {ranch_conns_sup, {ranch_conns_sup, start_link,
                    [Ref, ConnType, Shutdown, Transport, AckTimeout, Protocol]},
                permanent, infinity, supervisor, [ranch_conns_sup]},
            {ranch_acceptors_sup, {ranch_acceptors_sup, start_link,
                    [Ref, NbAcceptors, Transport, TransOpts]},
                permanent, infinity, supervisor, [ranch_acceptors_sup]}
        ],
        {ok, {{rest_for_one, 1, 5}, ChildSpecs}}.

    这里-behaviour(supervisor),就是典型的supervisor类型模块

    启动了ranch_conns_sup和ranch_acceptors_sup 2个进程

    这是ranch的主要工作模块才慢慢显露出来,下次我们重点分析这2个模块(未完待续...)

  • 相关阅读:
    Luogu P1273 有限电视网【树形Dp/树形背包】
    Luogu P1160队列安排【链表/老文搬家】By cellur925
    Luogu P1970 花匠 【线性Dp】 By cellur925
    Luogu P1541 乌龟棋 【线性dp】
    P2885 [USACO07NOV]电话线Telephone Wire——Chemist
    Luogu P3916 图的遍历 【优雅的dfs】【内有待填坑】By cellur925
    状压dp之二之三 炮兵阵地/玉米田 By cellur925
    Luogu P1991 无线通讯网 【最小生成树】
    浅谈并查集 By cellur925【内含题目食物链、银河英雄传说等】
    Luogu P1134 阶乘问题 【数学/乱搞】 By cellur925
  • 原文地址:https://www.cnblogs.com/tudou008/p/5473660.html
Copyright © 2011-2022 走看看