listener用于实现端口监听,接受连接, beyod支持单个进程中监听多个端口/多种协议。

配置文件中server组件listeners就是配置多个Listener组件。

功能特性:

  1. 支持TCP/UDP/Unix等底层传输层协议。
  2. 支持SSL,可以很容易实现类似https/wss等协议。
  3. 支持自定义协议(parser),可以实现任何应用层协议支持。
  4. 提供网络事件处理器机制(handler),可以很容易进行扩展。
  5. 支持reuse port特性,reuseport是一种套接字复用机制,它允许你将多个套接字bind在同一个IP地址/端口对上,这样一来,就可以建立多个服务来接受到同一个端口的连接。

Linux kernel 3.9开始提供reuse port支持。

  1. 客户端空闲超时检测及切断连接功能:
//每隔723秒检测一次,如果客户端超过7200秒没有发送有效的数据包,则判定为空闲超时,连接被服务器强制断开,释放资源。
keepalive_timeout=7200;
keepalive_interval=723;
//任何一个值设置为0,则关闭此功能

客户端连接异常断开(如死机、线路异常、对方程序崩溃)时,TCP连接本身无法感知这种问题,借助空闲连接检测机制,可以很容易释放无效连接,从而及时释放系统资源。

  1. 连接等待超时机制。有时我们希望客户端在tcp建连后必须在规定的时间内发送有效的完整数据包,以避免恶意客户端占用连接资源,listener组件提供了此机制:
//客户端tcp连接成功后,必须在10秒内发送一个完整的数据包,否则就被断开,默认0禁止此功能。
accept_timeout=10;
  1. IPV6支持。
  2. 支持同一个进程中多个listener组件监听。
  3. 支持运行时增加listener:
\Yii::$app->server->addListener($name, $listener)
  1. 支持运行时暂停接入功能:即将客户端的连接事件保留在操作系统backlog缓冲区内。

backlog是指客户端已经和服务器操作系统完成TCP三次握手,但还没有被应用层调用accept的连接队列。显然backlog的值不能过小。

\Yii::$app->server->getListener($name)->stopAccept(); //停止接入
\Yii::$app->server->getListener($name)->startAccept();//启动接入

使用指南

listener组件最重要的配置就是指定监听的协议和端口、协议解析器、事件处理器:

$listen

listen属性指定要监听的传输层协议和端口,形式为$scheme://$ip:$port或unix://$socket_file_path形式:

$scheme取值:tcp udp unix udg ssl tls sslv2 sslv3

$host:$port即为ip地址和端口, 0.0.0.0表示本机所有ip。

当使用ipv6时,ip部分必须使用方括号括起来。
tcp://[::]:891  表示本机ipv6任何地址的891端口

unix:///tmp/beyod.sock 表示一个unix socket套接字。
$parser

指定当前侦听器的应用层协议解析器, 可以是一个数组或字符串(parser类名),这也是使用了yii的组件化配置风格, 例如配置文件中指定

'http' => [
    'class' => 'beyod\Listener',
    'listen' => 'tcp://0.0.0.0:7725',
    'parser' => 'beyod\protocol\http\Parser',
    'handler' => [
        'class'=>'beyod\protocol\http\Handler',
        'gzip'=>true,
        'document_root' => dirname(__DIR__).'/webroot',
        'callback' =>[
                '#\.md$#' => function($event, $req, $res, $path){
                                $res->body = Markdown::process(file_get_contents($path), 'gfm-comment');
                                return true;
                            },
                ]
    ]
]
$hanlder

指定网络事件处理器组件配置,请参阅 “整体架构”章节。

总结:如果读者对yii框架较为熟悉,这些都是非常容易理解的配置格式。

$connections

当前套接字中的所有连接,群发信息时,就很有用:

foreach(\Yii::$app->server->getListener('http')->connections as $id => $conn){
    if($conn->isClosed()) continue;//跳过已经断开但还未释放的连接
    $conn->send($message);
}
$ssl

数组格式, 指定ssl套接字的参数,当使用ssl时,就必须设置$ssl属性。

ssl套接字配置参考:
http://php.net/manual/en/context.ssl.php
https://www.devdungeon.com/content/how-use-ssl-sockets-php