网络事件处理器,处理各种网络连接事件。
注意:beyod会为每个listener创建独立的handler对象,并不是为每个连接创建handler, 这是基于性能的考虑。
自定义的handler类,应该从beyoioHandler继承,并覆盖父类事件回调方法,实现自己的业务逻辑。
一般来说,最常用的回调是onMessage, onClose 即收到数据包、连接断开后的业务处理。
beyod/Handler.php
<?php
namespace beyod;
use yii\base\Event;
use beyod\CloseEvent;
use beyod\ErrorEvent;
use beyod\MessageEvent;
use yii\base\Behavior;
class Handler extends Behavior
{
/**
* @var Listenner 所属的Listener对象
*/
public $owner;
/**
* 当前handler支持的事件回调方法,一般来说,无须覆盖此方法。
*/
public function events()
{
return [
Server::ON_CONNECT => 'onConnect',
Server::ON_MESSAGE => 'onMessage',
Server::ON_CLOSE => 'onClose',
Server::ON_ERROR => 'onError',
Server::ON_BAD_PACKET => 'onBadPacket',
Server::ON_BUFFER_FULL => 'onBufferFull',
Server::ON_BUFFER_DRAIN => 'onBufferDrain',
Server::ON_SSL_HANDSHAKED => 'onSSLHandShaked',
Server::ON_UDP_PACKET => 'onUdpPacket',
Server::ON_START_ACCEPT => 'onStartAccept',
Server::ON_STOP_ACCEPT => 'onStopAccept',
];
}
/**
* handler对象被构造后调用的初始化方法,根据需要覆盖即可。
* @param Event $event
*/
public function init(){}
/**
* 当handler所属的listenner开始准备接收客户端连接时,此事件被激活。
* $event->sender即指向当前Listennner
*/
public function onStartAccept(Event $event){}
/**
* 同上,当前handler所属的listenner停止接收客户端连接时,此事件被激活。
* @param Event $event
*/
public function onStopAccept(Event $event){}
/**
* 当收到一个udp数据包时的回调
* @param UdpMessageEvent $event
$event->message即为当前数据包内容(具体格式与指定的Parser::decode方法有关)。
$event->sender为当前listenner对象。
*/
public function onUdpPacket(UdpMessageEvent $event){}
/**
* 当完整的tcp数据包解析成功后的事件回调。
* ```php
* $connection = $event->sender; //sender为当前connection对象
* $message= $event->message; //数据包内容
* $connection->send('hello, your request '.$message);
* ```
* @param MessageEvent $event
*/
public function onMessage(MessageEvent $event){}
/**
* 当一个tcp连接建立之后的事件回调, $event->sender为当前connection对象
* ```php
* $event->sender->send("hi, provide login: ");
* ```
* @param IOEvent $event
*/
public function onConnect(IOEvent $event){}
/**
* 当前tcp连接断开之后的事件回调 $event->by可以判断连接是被哪一方主动断开的。
* ```
* $event->by === CloseEvent::BY_SELF; //closed by self
* $event->by === CloseEvent::BY_PEER; //closed by remote
* ```
* @example 当前连接断开后,向其它客户端发送通知:
* ```
foreach($event->listenner->connections as $conn) {
if($conn->id == $event->sender->id || $conn->isClosed()) continue;
$conn->send($event->sender->id."");
}
*```
* @param CloseEvent $event
*/
public function onClose(CloseEvent $event){}
/**
* 输入输出过程中,出现错误,此事件被激活,一般来说,忽略即可(beyod会自己处理关闭连接)。
* ```php
* $event->code; //error code
* $event->errstr; //error messag
* $event->sender; //current connection
* ```
* @param ErrorEvent $event
*/
public function onError(ErrorEvent $event){
\Yii::error($event->sender." ".$event->errstr." ".$event->code, 'beyod');
}
/**
* 当数据包无法解析(过大,无法解析,格式错误)时,此事件激活(此时是否关闭连接,取决于你)。
* ```php
* $event->code; //error code
* $event->errstr; //error messag
* $event->sender; //current connection
* ```
* @param ErrorEvent $event
*/
public function onBadPacket(ErrorEvent $event){
\Yii::error($event->sender.' '.$event->code.' '.$event->errstr, 'beyoio');
$this->sendErrorResponse($event);
}
/**
* 当前连接的发送缓冲区已满时的事件回调,此时应该暂时发送,以免造成数据包丢失。
* 特别是发送大文件时,一定要注意缓冲区耗尽的问题,beyod自带的http server支持大文件(不限大小)下载,可参阅 beyoio\protocol\http\Handler::sendFile()
* ```php
* $event->code; //error code
* $event->errstr; //error messag
* $event->sender; //current connection
* ```
* @param IOEvent $event
*/
public function onBufferFull(IOEvent $event){}
/**
* 当前连接的发送缓冲区已空时的事件回调。发送大数据包时,应该使用这种方式,防止缓冲区耗尽。
* ```php
* $event->code; //error code
* $event->errstr; //error messag
* $event->sender; //current connection
* ```
* @param IOEvent $event
*/
public function onBufferDrain(IOEvent $event){
}
/**
* 当一个TCP SSL连接握手成功后的回调。一般无须重写此方法。
* @param IOEvent $event
*/
public function onSSLHandshaked(IOEvent $event){}
/**
* 当收到一个错误的数据包时,可以做一些期待的操作(如向客户端发送错误信息),如果要发送错误消息并断开连接:
$event->sender->close('invalid packet');
* 是否断开连接, 由开发者自行决定,beyod并不会武断地断开连接(而只是清空当前的接收缓冲区)
* @param ErrorEvent $event
*/
public function sendErrorResponse(ErrorEvent $event)
{
}
}