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

    接上 ranch 源码分析(三)

    在上一次,根据ranch源码把大概流程理了一遍,下面我们将一些细节解释一下。

     

    ranch只是一个服务的框架,它提供了传输层协议代码(ranch_tcp 和ranch_ssl),

    大概可以看看这2个的源码,其实就是gen_tcp和gen_ssl的封装。

    它做的工作可以分成

      1、根据port配置开启一个端口的linsten,(具体见ranch_acceptors_sup.erl代码)

      2、然后开启N个(根据设置)进程accpet等待client的连接, (具体见ranch_acceptors_sup.erl和ranch_acceptor.erl源码)

      3、当client连接,启动一个用户定义的应用protocol ,记录pid,(具体见ranch_conns_sup.erl源码)

      4、并把步骤2连接的socket的管理者改为步骤3的pid,剩下的就是应用模块去处理client的请求了,没ranch什么事情了(具体见下)

    首先在ranch_acceptor.erl中有如下代码

    -module(ranch_acceptor).

    -export([start_link/3]).
    -export([loop/3]).

    %.......省略若干行

    -spec loop(inet:socket(), module(), pid()) -> no_return(). loop(LSocket, Transport, ConnsSup) -> _ = case Transport:accept(LSocket, infinity) of {ok, CSocket} -> case Transport:controlling_process(CSocket, ConnsSup) of ok -> %% This call will not 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 after 100 -> ok end; %% We want to crash if the listening socket got closed. {error, Reason} when Reason =/= closed -> ok end,

    %.......省略若干行

    标记的地方能看到首先client连接成功的时候,会把scoket的所有者设置为Connsup 的pid

    然后在ranch_conns_sup.erl里面

    -module(ranch_conns_sup).

    %% API.
    -export([start_link/6]).
    -export([start_protocol/2]).
    -export([active_connections/1]).


    %.......省略若干行

    shoot(State=#state{ref=Ref, transport=Transport, ack_timeout=AckTimeout, max_conns=MaxConns}, CurConns, NbChildren, Sleepers, To, Socket, SupPid, ProtocolPid) -> case Transport:controlling_process(Socket, ProtocolPid) of ok -> ProtocolPid ! {shoot, Ref, Transport, Socket, AckTimeout}, put(SupPid, true), CurConns2 = CurConns + 1, if CurConns2 < 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, is supposed to be sitting under it and linked. exit(SupPid, kill), loop(State, CurConns, NbChildren, Sleepers) end.

    %.......省略若干行

    如上在Connsup中,会把scoket的所有者设置成Protocol启动处理业务的Pid~~~

    然后就没有然后呢,其实ranch只是一个框架,具体的应用实现还是要靠用户去编写,

    不过好在我们有优秀的例子,比如cowboy的新版(V1.0.4版本以上)就是ranch的最好的例子之一。

    ranch的介绍到这里就结束了,读者有疑问的请到下面提出。

  • 相关阅读:
    ESA2GJK1DH1K开发教程: 来看看最新整理的整个开发板的教程大纲吧
    关于STM32 Flash的一些问题
    关于单片机的RAM
    单片机模块化程序: 单片机加入JSON是个不错的选择
    YY天气使用
    单片机模块化程序: 给单片机写个回调函数怎么样
    单片机模块化程序: 单片机AT指令配置模块程序模板(非阻塞版)
    单片机模块化程序: 单片机AT指令配置模块程序模板(阻塞版)
    【java基础】java集合之TreeMap
    【java基础】java集合之HashTable,HashSet,HashMap
  • 原文地址:https://www.cnblogs.com/tudou008/p/5484911.html
Copyright © 2011-2022 走看看