设为首页收藏本站

Erlang中文论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 623|回复: 0

ranch初窥2

[复制链接]
发表于 2018-7-13 17:24:53 | 显示全部楼层 |阅读模式
本帖最后由 茶叶feng 于 2018-7-13 17:26 编辑

# 接《ranch初窥1》#
- 从我的有道云笔记转过来的, 可以直接访问连接http://note.youdao.com/noteshare?id=20b0bc4806aed935da3f258816eae7da&sub=AF84BFF80C114F3898D6FC07648EEC99
## ranch_listener_sup.erl ##
该监控进程启动时,主动调用ranch\_server:set\_listener\_sup/2,将自己的信息记录在ets中并且被ranch\_server监控,它下面还顺序启动了ranch\_conns\_sup和ranch\_acceptors\_sup,策略是rest\_for\_one,因为ranch\_conns\_sup是负责监控连接的进程,而ranch\_acceptors\_sup是监控消息的进程,ranch\_conns\_sup死掉之后,说明连接都断开了,ranch\_acceptors\_sup下面的进程也就无法运行,必须等ranch\_conns\_sup重启成功后才能正常工作。
## ranch_conns_sup.erl ##
该模块并不是supervisor行为,不过作者手动写了一个类似supervisor的东西,启动时主动调用ranch\_server:set\_connections\_sup/2记录自身的信息,同时通过ranch\_server获取相应的一些连接参数,其中用到了proc\_lib:init\_ack/2用于响应proc\_lib:start\_link/3,实现同步启动进程,做到和gen\_server一样的效果,接着开始一个循环函数loop/4,用来处理消息,下面列出主要的消息处理
{?MODULE, start\_protocol, T, Socket}:参数中To为ranch\_acceptor模块的进程pid,而Socket是ranch\_acceptor接收到的客户端socket,启动一个调用Protocol:start\_link/4启动一个进程,这个Protocol是用户实现的回调模块,通常是socket消息的接收处理进程,就像例子中的echo\_protocol.erl或者reverse\_protocol.erl这两个部分,如果启动成功,将会调用shoot/8来修改回调模块的Socket的控制进程,即socket的消息将发送到哪个进程在这里决定,修改之后,将回复回调部分进程一个{shoot, Ref, Transport, Socket, AckTimeout}消息,接着检查当前连接数量是否达到配置中的MaxConns,如果达到了最大连接数的话则把连接加入到等待连接列表中,同时增加子连接数量,继续循环loop/4
{?MODULE, active\_connections, To, Tag}:To连接进程获取当前连接列表
{remove\_connection, Ref, Pid}:移除某个连接进程
```
-spec init(pid(), ranch:ref(), module(), module()) -> no_return().
init(Parent, Ref, Transport, Protocol) ->
        process_flag(trap_exit, true),
        ok = ranch_server:set_connections_sup(Ref, self()),
        MaxConns = ranch_server:get_max_connections(Ref),
        TransOpts = ranch_server:get_transport_options(Ref),
        ConnType = proplists:get_value(connection_type, TransOpts, worker),
        Shutdown = proplists:get_value(shutdown, TransOpts, 5000),
        AckTimeout = proplists:get_value(ack_timeout, TransOpts, 5000),
        ProtoOpts = 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=ProtoOpts, ack_timeout=AckTimeout, max_conns=MaxConns}, 0, 0, []).
```



回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|Erldoc.com  

GMT+8, 2019-7-23 23:18 , Processed in 0.024202 second(s), 9 queries , File On.

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表