当beyod server需要和其它服务器交互时, 这时就作为tcp/udp/unix socket客户端,StreamClient提供了此功能支持。
一般来说,应该在Server::onWorkerStart或Handler::init方法中初始化StreamClient连接。以下是一个异步Redis连接过程。
appMyServer
<?php
namespace app;
use Yii;
use beyod\Server;
use beyod\dispatcher\Client;
use beyod\MessageEvent;
use beyod\IOEvent;
use beyod\protocol\redis\Request;
use beyod\protocol\dns\Message;
class MyServer extends \beyod\Server
{
public $redis_server = 'tcp://192.168.1.19:6379';
public $redisClient;
public function onWorkerStart($workerId, $GPID)
{
parent::onWorkerStart($workerId, $GPID);
$this->connectRedisServer(); //工作进程启动后,就开始连接到Redis服务器
}
protected function connectRedisServer()
{
//设置连接目标,重连间隔,连接超时时间
$options = [
'target' => $this->redis_server,
'reconnect_interval' => 5, //连接异常断开, 5秒后重连
'timeout' => 10, //连接超时10秒
];
//初始化一个连接对象,此时还未开始连接
$this->redisClient = new \beyod\protocol\redis\Client($options);
//收到数据时的回调
$this->redisClient->on(Server::ON_MESSAGE, function($event){
/**
* @var MessageEvent $event
* @var Request $event->message
* */
print_r($event->message);
});
//连接成功之后就可以发送数据了
$this->redisClient->on(Server::ON_CONNECT, function(IOEvent $event){
Yii::debug($event->sender.' connect ok ');
$this->redisClient->set('a',serialize($_SERVER));
$this->redisClient->get('a');
});
//事件回调成功 开始连接。
$this->redisClient->connect();
}
}
beyodStreamClient实现了基础的客户端连接,自定义协议时,应该在此类上扩展实现。
常量:
const STATUS_CONNECTING = 1;
正在建立状态
const STATUS_ESTABLISHED = 2;
连接已经建立
const STATUS_CLOSED = 1;
连接已经关闭 连接失败,被动关闭或主动关闭
属性
static $connections = [];
当前所有StreamClient对象,键名为id, 值为StreamClient对象
$reconnect_interval = 0;
连接失败或连接被动关闭时,重新连接间隔秒数,0表示断开后不自动重新连接,此值可以使用小数。
$options=[];
socket创建时的选项,参阅: http://php.net/manual/en/function.socket-set-option.php
http://php.net/manual/en/sockets.constants.php
键名为选项常量名而不是常量值。
默认的选项参数:
<pre>
'backlog' => 256, //tcp连接队列值
'SO_REUSEADDR' => 1, //重用已经断开的连接5元组,对需要建立大量短连接的客户端,必须设置此值
'SO_KEEPALIVE' => 1, //启用系统内核层的tcp keepalive机制
'SO_LINGER' => null,
'SO_SNDBUF' => null,
'SO_RCVBUF' => null,
'TCP_NODELAY' => 1
</pre>
$ssl=[];
使用ssl连接时的选项,
可使用的选项: http://php.net/manual/en/context.ssl.php
php ssl使用方法: https://www.devdungeon.com/content/how-use-ssl-sockets-php
默认选项:
<pre>
'enabled' => false, //是否启用ssl
'verify_peer' => false, //是否验证服务器证书
'verify_perr_name' => false, //是否验证对方主机名
'allow_self_signaed' => true, //是否允许自签名的证书
</pre>
public string $target;
//连接目标, 传输层协议/目标地址/端口三部分组成,如果使用ipv6, ip部分必须使用方括号括起来。
http://php.net/manual/en/transports.inet.php
http://php.net/manual/en/transports.unix.php
public int $timeout=30;
连接超时秒数, 0表示使用系统默认超时值。
public int $max_send_buffer_size=10485760;
单个连接的发送缓冲区字节数,如果缓冲区内容超出此值,Server::ON_BUFFER_FULL事件将被激活,并且开始丢弃最新的发送数据包。
public $read_buffer_size = 65536;
接收数据时,每次读取的字节数,一般无须修改此值
public string|array|Parser $parser;
协议解析器组件配置信息,可以是解析器类名、配置数组、Parser对象。
public string $peer;
连接对端的地址和端口,分号连接
public string $local;
本地地址和端口,只有在连接建立后才有意义。
方法
public function pipe(Connection $target);
为当前连接设置管道连接,常用来作代理、数据库连接池等。
StreamClient代表了beyod与后端服务器的连接,而Connection为客户端与beyod之间的连接,客户端的任何数据包,将原样通过StreamClient发送给后端服务器,而后端服务器返回的数据,将通过Connection发送给客户端,从而实现代理转发机制。
public function unpipe(void);
同上,取消管道连接
public void function setAttribute(string $name, $value=null);
为当前连接设置一个属性,参数分别为属性名称,属性值,null表示删除指定的属性名。例如我们可以在连接建立之后,将客户端的验证状态,客户端参数保存在连接对象上,后续交互中就可以通过getAttribute($name)取得此属性值。
public mixed function getAttribute($name, $default = null);
同上,读取指定的属性的值
public bool function hasAttribute($name);
判断指定的属性值是否存在
public bool function getIsClosed();
判断当前连接是否为关闭状态
public bool function getIsEstablished();
判断当前连接是否为已经建立状态
public function __toString(){
return "$this->id $this->peer $this->local";
}
__toString魔术方法
public int getId();
当前连接的id, beyod使用id复用机制,不存在连接id持续增长耗尽的问题。
public StreamClient connect($renew=false)
开始连接,$renew:是否强制重新连接,否则只有在连接未建立或关闭的情况下才重新连接
public StreamClient function prepare()
针对udp,使用prepare而不是connect, 为了保持字面上的意义(虽然本质上是调用了connect)。
public string getScheme()
获取传输层协议
public bool isSSL()
判断当前连接是否启用SSL
public bool isTCP() 是否为tcp
public bool isUDP() 是否为udp/udg
public function isUnix() 是否为unix套接字
public int send(mixed $message, $raw=false)
向服务器发送数据, $raw:是否只发送原始字节流而不使用parser封包。
public void close()
主动关闭当前连接
public float getResponseAt()
获取服务器最近响应数据到达时间戳
public float getConnectAt()
最近一次连接建立时间戳
事件 | 功能 | 参数类型 |
---|---|---|
Server::ON_CONNECT_FAILED | 连接失败 | ErrorEvent |
Server::ON_CLOSE | 连接被动或主动关闭 | CloseEvent |
Server::ON_BEFORE_CONNECT | 准备连接前 | IOEvent |
Server::ON_CONNECT | 连接建立成功 | IOEvent |
Server::ON_BAD_PACKET | 收到错误的数据包 | ErrorEvent |
Server::ON_MESSAGE | 收到完整数据包 | MessageEvent |
Server::ON_BUFFER_FULL | 缓冲区已满 | IOEvent |
Server::ON_BUFFER_DRAIN | 缓冲区已空 | IOEvent |