bobby / servers
原生PHP实现的异步即时网络通信服务组件
Requires
- ext-openssl: *
- ext-pcntl: *
- ext-posix: *
- ext-sockets: *
- ext-zlib: *
- bobby/server-network-protocol: master-dev
- bobby/stream-event-loop: master-dev
This package is auto-updated.
Last update: 2024-11-12 11:56:56 UTC
README
示例:
TCP SERVER:
<?php require __DIR__ . "/../vendor/autoload.php"; use Bobby\StreamEventLoop\LoopFactory; use Bobby\Servers\Socket; use Bobby\Servers\ServerConfig; use Bobby\Servers\Tcp\Server; use Bobby\Servers\Contracts\ConnectionContract; $loop = LoopFactory::make(); $serveSocket = new Socket("0.0.0.0:80"); $config = new ServerConfig(); $tcp = new Server($serveSocket, $config, $loop); $tcp->on(Server::CONNECT_EVENT, function (Server $server, ConnectionContract $connection) { echo 'Socket ' . (int)$connection->exportStream() . ' connected.', PHP_EOL; }); $tcp->on(Server::RECEIVE_EVENT, function (Server $server, ConnectionContract $connection, $data) { echo "Receive message:$data", PHP_EOL; $server->send($connection, "HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nHi"); $server->close($connection); }); $tcp->on(Server::CLOSE_EVENT, function (Server $server, ConnectionContract $connection) { echo 'Socket ' . (int)$connection->exportStream() . ' is closed.', PHP_EOL; }); $tcp->on(Server::ERROR_EVENT, function (Server $server, ConnectionContract $connection, Throwable $exception) { echo $exception->getTraceAsString(), PHP_EOL; die; }); $tcp->listen(); $loop->poll();
HTTP SERVER:
require __DIR__ . '/../vendor/autoload.php'; $loop = \Bobby\StreamEventLoop\LoopFactory::make(); $serveSocket = new \Bobby\Servers\Socket('0.0.0.0:80'); $config = new \Bobby\Servers\ServerConfig(); $http = new \Bobby\Servers\Http\Server($serveSocket, $config, $loop); $http->on(\Bobby\Servers\Http\Server::REQUEST_EVENT, function ( \Bobby\Servers\Http\Server $server, \Bobby\ServerNetworkProtocol\Http\Request $request, \Bobby\Servers\Http\Response $response ) { $request->compressToEnv(); var_dump($_POST, $_GET, $_FILES, $_SERVER, $_FILES); $response ->gzip(5) ->header('Vary', 'Accept-Encoding') ->header('Content-Type', 'text/html; charset=UTF-8') ->end("how are you34567~~~你好啊是"); // $response->redirect('http://www.baidu.com/'); // // $response // ->header('Content-Type', 'text/html; charset=UTF-8') // ->header("Extract", 1) // ->cookie("PHPSSID", 123) // ->chunk("分段传输开始") // ->chunk("Hello world!!!!~") // ->chunk("Yoyo.") // ->chunk("PHP is best language.") // ->chunk("最后一块") // ->end(); }); $http->listen(); $loop->poll();
WEBSOCKET SERVER:
<?php require __DIR__ . "/../vendor/autoload.php"; $loop = \Bobby\StreamEventLoop\LoopFactory::make(); $serveSocket = new \Bobby\Servers\Socket("0.0.0.0:80"); $config = new \Bobby\Servers\ServerConfig(); $websocket = new Bobby\Servers\Websocket\Server($serveSocket, $config, $loop); $websocket->on(\Bobby\Servers\Websocket\Server::OPEN_EVENT, function ( \Bobby\Servers\Websocket\Server $server, \Bobby\Servers\Connection $connection, \Bobby\ServerNetworkProtocol\Http\Request $request ) { echo "Socket:" . $connection->exportStream() . " opened.\n"; }); $websocket->on(\Bobby\Servers\Websocket\Server::MESSAGE_EVENT, function ( \Bobby\Servers\Websocket\Server $server, \Bobby\Servers\Connection $connection, \Bobby\ServerNetworkProtocol\Websocket\Frame $frame ) { foreach ($server->getShookConnections() as $connection) { $data = json_decode($frame->payloadData); $data->time = date('Y-m-d H:i:s'); $data = json_encode($data); $server->getPusher()->pushString($connection, $data); } }); $websocket->on(\Bobby\Servers\Websocket\Server::REQUEST_EVENT, function ( \Bobby\Servers\Websocket\Server $server, \Bobby\ServerNetworkProtocol\Http\Request $request, \Bobby\Servers\Http\Response $response ) { if (isset($request->get['msg'])) { foreach ($server->getShookConnections() as $connection) { $data = json_encode(['content' => $request->get['msg'], 'username' => 'admin', 'type' => 2, 'time' => date('Y-m-d H:i:s')]); $server->getPusher()->pushString($connection, $data); } } $response->end(json_encode(['code' => 1, 'msg' => 'ok!'])); }); $websocket->listen(); $loop->poll();
UDP SERVER:
<?php require __DIR__ . "/../vendor/autoload.php"; $loop = \Bobby\StreamEventLoop\LoopFactory::make(); $serveSocket = new \Bobby\Servers\Socket('0.0.0.0:80'); $config = new \Bobby\Servers\ServerConfig(); $udp = new \Bobby\Servers\Udp\Server($serveSocket, $config, $loop); $udp->on(\Bobby\Servers\Udp\Server::RECEIVE_EVENT, function (\Bobby\Servers\Udp\Server $server, $address, string $message) { echo "Receive socket address:$address and data:$message", PHP_EOL; $written = $server->sendTo($address, 'ok!'); echo "Send buffer num $written", PHP_EOL; }); $udp->on(\Bobby\Servers\Udp\Server::ERROR_EVENT, function (\Bobby\Servers\Udp\Server $server, Throwable $exception) { echo $exception->getTraceAsString(); }); $udp->listen(); $loop->poll();
UNIX SERVER:
<?php require __DIR__ . "/../vendor/autoload.php"; $serveSocket = new \Bobby\Servers\Socket("/var/run/myserv.sock"); $config = new \Bobby\Servers\ServerConfig(); $loop = \Bobby\StreamEventLoop\LoopFactory::make(); $unixDomain = new \Bobby\Servers\Unix\Server($serveSocket, $config, $loop); $unixDomain->on( \Bobby\Servers\Unix\Server::CONNECT_EVENT, function ( \Bobby\Servers\Unix\Server $server, \Bobby\Servers\Contracts\ConnectionContract $connection ) { echo 'Socket ' . (int)$connection->exportStream() . ' connected.', PHP_EOL; }); $unixDomain->on( \Bobby\Servers\Unix\Server::RECEIVE_EVENT, function ( \Bobby\Servers\Unix\Server $server, \Bobby\Servers\Contracts\ConnectionContract $connection, $data ) { echo "Receive message:$data", PHP_EOL; $server->send($connection, "HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nHi"); $server->close($connection); }); $unixDomain->on( \Bobby\Servers\Unix\Server::CLOSE_EVENT, function ( \Bobby\Servers\Unix\Server $server, \Bobby\Servers\Contracts\ConnectionContract $connection ) { echo 'Socket ' . (int)$connection->exportStream() . ' is closed.', PHP_EOL; }); $unixDomain->on( \Bobby\Servers\Unix\Server::ERROR_EVENT, function ( \Bobby\Servers\Unix\Server $server, \Bobby\Servers\Contracts\ConnectionContract $connection, Throwable $exception ) { echo $exception->getTraceAsString(), PHP_EOL; die; }); $unixDomain->listen(); $loop->poll();
(以下仅说明常用api,其他api可以通过读源码获得)
基础公共类
Bobby\Servers\ServerConfig 服务器基础配置
method:
public function setProtocolOptions(array $protocolOptions)
用于配置如何解析从网络上收到的原始消息,比如处理粘包拆包,合包,解析websocket数据帧格式等。
参数:
$protocolOptions array 消息解析协议配置,不同类型server配置内容不同。
public function setServeOptions(array $serveOptions)
参数:
$serveOptions array 用于server运行行为状态配置,不同类型server配置内容不同。
Bobby\Servers\Socket 用于表示运行服务器的socket对象。
method:
final public function __construct(string $address, array $context = [])
参数:
$address string 合法的服务器地址,如:"0.0.0.0:80"或者unix地址"/tmp/php.sock"。
$context array socket上下文参数,同stream_context_create参数一样。
public function isOpenedSsl(): bool
检测是否设置了ssl相关上下文。
public function getAddress(): string
获取socket地址,同构造函数传入的地址
public function getContext()
获取socket上下文。
Bobby\Servers\Connection 用于表示客户端和服务器维持的连接。
method:
public function isOpenedSsl(): bool
判断连接是否开启ssl加密。
public function exportStream()
获取和连接关联的socket stream。
public function isPaused(): bool
判断连接是否停止接收数据。
public function pause()
停止读写客户端数据。
public function resume()
回复读写客户端发送来的数据。
public function getRemoteAddress(): string
获取客户端地址。
public function isClosed(): bool
判断客户端是否已关闭。
public function getLastReceiveTime(): ?int
获取上次读取连接数据的时间戳。null代表没有接收过数据。
Bobby\Servers\ConnectionPool
客户端和server的维持连接的Connection对象连接池送代器,可用于送代正在维持连接的Connection对象。
TCP SERVE:
Bobby\Servers\Tcp\Server TCP服务器对象
method:
public function __construct(Bobby\Servers\Contracts\SocketContract $serveSocket, Bobby\Servers\Contracts\ServerConfigContract $config, Bobby\StreamEventLoop\LoopContract $eventLoop)
参数:
$serverSocket Bobby\Servers\Contracts\SocketContract 传入Bobby\Servers\Socket对象。
$config Bobby\Servers\Contracts\ServerConfigContract 传入Bobby\Servers\ServerConfig对象。可配置项:
public function setProtocolOptions(array $protocolOptions)
参数可传入配置同Bobby\ServerNetworkProtocol\Tcp\Parser::__construct(array $decodeOptions = [])参数。详见 https://packagist.org/packages/bobby/server-network-protocol
public function setServeOptions(array $serveOptions)
可用配置项:
max_connection int 接收的最大连接数。
receive_buffer_size int 每个连接能够缓冲的最大单个包长字节数。如果发来的数据包解析得到的不完整包包长大于该参数,则会视为非法数据,会触发on error事件回调并且传入Bobby\Servers\Exceptions\ReceiveBufferFullException实例。
如:
$config->setServeOptions(
[
'max_connection' => 1000,
'receive_buff_size' => 1024,
]
)
$eventLoop Bobby\StreamEventLoop\LoopContract 实现了Bobby\StreamEventLoop\LoopContract接口的事件循环对象,可以使用\Bobby\StreamEventLoop\LoopFactory::make()获得。(注意:所有server都需要依赖该对象运行)详见:https://packagist.org/packages/bobby/stream-event-loop
public function getConnections(): Bobby\Servers\Contracts\ConnectionPoolContract
获取Bobby\Servers\Connection对象池送代器。可用于送代表示和服务器正在保持连接的客户端的Connection对象。
public function on(string $event, callable $listener)
设置回调。可设置回调包括:
use Bobby\Servers\Tcp\Server; use Bobby\Servers\Contracts\ConnectionContract; // 当有新连接时间发生时候触发 $tcp->on(Server::CONNECT_EVENT, function (Server $server, ConnectionContract $connection) { echo 'Socket ' . (int)$connection->exportStream() . ' connected.', PHP_EOL; }); // 当有消息时候触发 $tcp->on(Server::RECEIVE_EVENT, function (Server $server, ConnectionContract $connection, $data) { echo "Receive message:$data", PHP_EOL; $server->send($connection, "HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nHi"); $server->close($connection); }); // 当有连接关闭时触发 $tcp->on(Server::CLOSE_EVENT, function (Server $server, ConnectionContract $connection) { echo 'Socket ' . (int)$connection->exportStream() . ' is closed.', PHP_EOL; }); // 当server进程有用户程序意外错误发生时候回调 $tcp->on(Server::ERROR_EVENT, function (Server $server, ConnectionContract $connection, Throwable $exception) { echo $exception->getTraceAsString(), PHP_EOL; die; }); // 当连接满的时候触发 $tcp->on(Server::CONNECT_FULL_EVENT, function (Server $server, ConnectionContract $connection) { $server->send($connection, "connection full."); });
public function pause()
服务器停止接收连接和读取客户端数据。
public function resume()
服务器回复接收连接和读取数据。
public function close(Bobby\Servers\Contracts\ConnectionContract $connection, bool $force = false)
关闭客户端连接。
参数:
$connection Bobby\Servers\Contracts\ConnectionContract 连接对象。
$force bool 表示是否强制关闭连接。如果否则会在连接所有数据发送完毕后关闭连接,否则表示立即关闭连接。
public function send(Bobby\Servers\Contracts\ConnectionContract $connection, string $message): bool
给连接的客户端发送数据。该操作是异步操作,不会产生IO阻塞。
参数:
$connection Bobby\Servers\Contracts\ConnectionContract 需要发送的连接对象。
$message string 消息。
public function listen()
server开始监听连接。
public function getEventLoop(): Bobby\StreamEventLoop\LoopContract
获取通过构造函数传入的事件循环对象Bobby\StreamEventLoop\LoopContract接口实现类,可用于处理异步逻辑编程,定时器等功能,详见功能见:https://packagist.org/packages/bobby/stream-event-loop
public function getServeSocket(): Bobby\Servers\Contracts\SocketContract
获取Bobby\Servers\Socket对象实例。
示例:
<?php require __DIR__ . "/../vendor/autoload.php"; use Bobby\StreamEventLoop\LoopFactory; use Bobby\Servers\Socket; use Bobby\Servers\ServerConfig; use Bobby\Servers\Tcp\Server; use Bobby\Servers\Contracts\ConnectionContract; $loop = LoopFactory::make(); $serveSocket = new Socket("0.0.0.0:80"); $config = new ServerConfig(); $tcp = new Server($serveSocket, $config, $loop); $tcp->on(Server::CONNECT_EVENT, function (Server $server, ConnectionContract $connection) { echo 'Socket ' . (int)$connection->exportStream() . ' connected.', PHP_EOL; }); $tcp->on(Server::RECEIVE_EVENT, function (Server $server, ConnectionContract $connection, $data) { echo "Receive message:$data", PHP_EOL; $server->send($connection, "HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nHi"); $server->close($connection); }); $tcp->on(Server::CLOSE_EVENT, function (Server $server, ConnectionContract $connection) { echo 'Socket ' . (int)$connection->exportStream() . ' is closed.', PHP_EOL; }); $tcp->on(Server::ERROR_EVENT, function (Server $server, ConnectionContract $connection, Throwable $exception) { echo $exception->getTraceAsString(), PHP_EOL; die; }); // 监听服务 $tcp->listen(); // 运行evntloop 服务随之运行 $loop->poll();
Unix Server方法同Tcp Server
Http Server
Bobby\Servers\Http\Server HTTP服务器对象。继承自Bobby\Servers\Tcp\Server,拥有从Bobby\Servers\Tcp\Server继承的方法。
和tcp server不同点:
构造函数参数Bobby\Servers\ServerConfig对象可设置配置项:
public function setProtocolOptions(array $protocolOptions)
参数可传入配置同Bobby\ServerNetworkProtocol\Http\Parser::__construct(array $decodeOptions = [])参数。详见 https://packagist.org/packages/bobby/server-network-protocol
public function setServeOptions(array $serveOptions)
可用配置项:
max_connection int 接收的最大连接数。
receive_buffer_size int 每个连接能够缓冲的最大单个包长字节数。如果发来的数据包解析得到的不完整包包长大于该参数,则会视为非法数据,会触发on error事件回调并且传入Bobby\Servers\Exceptions\ReceiveBufferFullException实例。
keep_alive_timeout int 当http客户端发生connection keep alive header时保持的连接时长秒数。不设置则server默认保持60s。
如:
$config->setServeOptions(
[
'max_connection' => 1000,
'keep_alive_timeout' => 65,
]
)
可设置回调:
// 有请求到达时候回调 $http->on(\Bobby\Servers\Http\Server::REQUEST_EVENT, function ( \Bobby\Servers\Http\Server $server, \Bobby\ServerNetworkProtocol\Http\Request $request, \Bobby\Servers\Http\Response $response ) { $request->compressToEnv(); var_dump($_POST, $_GET, $_FILES, $_SERVER, $_FILES); // 模拟异步请求远程api $remote = fsockopen($host = 'www.baidu.com', 80); $post = "GET / HTTP/1.1\r\n"; $post .= "Host: $host\r\n"; $post .= "Connection: close\r\n\r\n"; $server->getEventLoop()->addLoopStream( \Bobby\StreamEventLoop\LoopContract::WRITE_EVENT, $remote, function ($remote, \Bobby\StreamEventLoop\LoopContract $loop) use ($host, &$post) { if (($written = fwrite($remote, $post)) === strlen($post)) { sleep(2); $loop->removeLoopStream(\Bobby\StreamEventLoop\LoopContract::WRITE_EVENT, $remote); $loop->addLoopStream(\Bobby\StreamEventLoop\LoopContract::READ_EVENT, $remote, function ($remote, \Bobby\StreamEventLoop\LoopContract $loop) { $data = fread($remote, 1024); echo $data; $loop->removeLoopStream(\Bobby\StreamEventLoop\LoopContract::READ_EVENT, $remote); }); } else { $post = substr($post, 0, $written); } }); $response ->gzip(5) ->header('Vary', 'Accept-Encoding') ->header('Content-Type', 'text/html; charset=UTF-8') ->end("how are you34567~~~你好啊是"); // $response->redirect('http://www.baidu.com/'); // // $response // ->header('Content-Type', 'text/html; charset=UTF-8') // ->header("Extract", 1) // ->cookie("PHPSSID", 123) // ->chunk("分段传输开始") // ->chunk("Hello world!!!!~") // ->chunk("Yoyo.") // ->chunk("PHP is best language.") // ->chunk("最后一块") // ->end(); }); // server关闭时候回调 $http->on(\Bobby\Servers\Http\Server::CLOSE_EVENT, function (\Bobby\Servers\Http\Server $server, \Bobby\Servers\Connection $connection) { echo 'Socket ' . (int)$connection->exportStream() . ' is closed.', PHP_EOL; }); // 当server进程有用户程序意外错误发生时候回调 $http->on(\Bobby\Servers\Http\Server::ERROR_EVENT, function (\Bobby\Servers\Http\Server $server, \Bobby\Servers\Connection $connection, Throwable $exception) { echo $exception->getTraceAsString(), PHP_EOL; die; });
on request回调事件用到的对象:
Bobby\ServerNetworkProtocol\Http\Request 详见https://packagist.org/packages/bobby/server-network-protocol
Bobby\Servers\Http\Response 响应对象。
method:
public function header(string $header, string $value, bool $ucwords = true)
设置 HTTP 响应的 Header 信息
参数:
header string 设置必须在 end 方法之前 -$key 必须完全符合 Http 的约定,每个单词首字母大写,不得包含中文,下划线或者其他特殊字符。
$value string 必须填写。
$ucwords bool 设为 true,底层会自动对 $key 进行约定格式化。
public function status(int $statusCode = ResponseCodeEnum::HTTP_OK, $reason = '')
发送 Http 状态码。如果只传入了第一个参数 $statusCode 必须为合法的 HttpCode,如 200、502、301、404 等,否则会设置为 200 状态码
如果设置了第二个参数 $reason,$statusCode 可以为任意的数值,包括未定义的 HttpCode,如 499。必须在 $response->end() 之前执行 status 方法
public function gzip(int $level = -1)
压缩等级,等级越高压缩后的尺寸越小,但 CPU 消耗更多。
参数:
$level int 压缩等级。-1代表采用默认等级压缩。
public function cookie(string $key, string $value = '', int $expire = 0, string $path = '/', string $domain = '', bool $secure = false, bool $httpOnly = false, $isRaw = false)
设置 HTTP 响应的 cookie 信息。此方法参数与 PHP 的 setcookie 完全一致。会自动会对 $value 进行 urlencode 编码,可使用$isRaw关闭对 $value 的编码处理
public function end(string $content = '')
发送 Http 响应体,并结束请求处理。该操作是异步操作,不会产生IO阻塞。
public function chunk(string $content)
启用 Http Chunk 分段向浏览器发送相应内容。该操作是异步操作,不会产生IO阻塞。
public function redirect(string $url, $statusCode = 302)
发送 Http 跳转。调用此方法会自动 end 发送并结束响应。
public function make(): Bobby\Servers\Http\Response
构造新的Response 对象。
Websocket server
Bobby\Servers\Websocket\Server Websocket服务器对象。继承自Bobby\Servers\Http\Server,拥有从Bobby\Servers\Http\Server继承的方法。
和http server不同点:
新增方法:
public function getPusher(): Bobby\Servers\Websocket\Pusher
获取websocket消息推送器。推送器所有推送操作都是异步操作,不会产生IO操作。Bobby\Servers\Websocket\Pusher提供以下方法:
public function ping(Connection $connection)
发生ping包
public function pong(Connection $connection)
发生pong包
public function pushString(Connection $connection, string $message)
推送字符串消息
public function pushFile(Connection $connection, string $message)
推送文件内容。$message为文件内容。
public function notifyClose(Connection $connection)
通知客户端server准备关闭连接。
public function getShookConnections(): Bobby\Servers\ConnectionPool
和getConnections方法类似,不同的是获取已经进行websocket握手升级的Connection对象池送代器
构造函数参数Bobby\Servers\ServerConfig对象可设置配置项:
public function setProtocolOptions(array $protocolOptions)
参数可传入配置同Bobby\ServerNetworkProtocol\Websocket\Parser::__construct(array $decodeOptions = [])参数。详见 https://packagist.org/packages/bobby/server-network-protocol
public function setServeOptions(array $serveOptions)
可用配置项:
max_connection int 接收的最大连接数。
receive_buffer_size int 每个连接能够缓冲的最大单个包长字节数。如果发来的数据包解析得到的不完整包包长大于该参数,则会视为非法数据,会触发on error事件回调并且传入Bobby\Servers\Exceptions\ReceiveBufferFullException实例。
keep_alive_timeout int 当http客户端发生connection keep alive header时保持的连接时长秒数。不设置则server默认保持60s。
如:
$config->setServeOptions(
[
'max_connection' => 1000,
'keep_alive_timeout' => 65,
]
)
可设置回调: 除了包括所有http server可设置回调,还包括以下新增回调:
// 当和websocket客户端握手后回调
$websocket->on(\Bobby\Servers\Websocket\Server::OPEN_EVENT, function (
\Bobby\Servers\Websocket\Server $server,
\Bobby\Servers\Connection $connection,
\Bobby\ServerNetworkProtocol\Http\Request $request
) {
echo "Socket:" . $connection->exportStream() . " opened.\n";
});
// 当接收到websocket客户端消息时候回调
$websocket->on(\Bobby\Servers\Websocket\Server::MESSAGE_EVENT, function (
\Bobby\Servers\Websocket\Server $server,
\Bobby\Servers\Connection $connection,
\Bobby\ServerNetworkProtocol\Websocket\Frame $frame
) {
foreach ($server->getShookConnections() as $connection) {
// $frame->payloadData获取websocket客户端发送来的消息
$data = json_decode($frame->payloadData);
$data->time = date('Y-m-d H:i:s');
$data = json_encode($data);
$server->getPusher()->pushString($connection, $data);
}
});
// 当接收到websocket客户端ping包格式数据帧时候回调
$websocket->on(\Bobby\Servers\Websocket\Server::PING_EVENT, function (
\Bobby\Servers\Websocket\Server $server,
\Bobby\Servers\Connection $connection,
) {
$serer->getPusher()->pong($connection);
});
UDP SERVER:
Bobby\Servers\Udp\Server UDP服务器对象
method:
public function __construct(Bobby\Servers\Contracts\SocketContract $serveSocket, Bobby\Servers\Contracts\ServerConfigContract $config, Bobby\StreamEventLoop\LoopContract $eventLoop)
参数:
$serverSocket Bobby\Servers\Contracts\SocketContract 传入Bobby\Servers\Socket对象。
$config Bobby\Servers\Contracts\ServerConfigContract 传入Bobby\Servers\ServerConfig对象。可配置项:
public function setProtocolOptions(array $protocolOptions)
无可设置项
public function setServeOptions(array $serveOptions)
无可设置项目
$eventLoop Bobby\StreamEventLoop\LoopContract 实现了Bobby\StreamEventLoop\LoopContract接口的事件循环对象,可以使用\Bobby\StreamEventLoop\LoopFactory::make()获得。(注意:所有server都需要依赖该对象运行)详见:https://packagist.org/packages/bobby/stream-event-loop。
public function on(string $event, callable $listener)
设置回调。可设置回调包括:
// 当消息到达时触发回调 $udp->on(\Bobby\Servers\Udp\Server::RECEIVE_EVENT, function (\Bobby\Servers\Udp\Server $server, $address, string $message) { echo "Receive socket address:$address and data:$message", PHP_EOL; $written = $server->sendTo($address, 'ok!'); echo "Send buffer num $written", PHP_EOL; }); // 当进程发生用户程序意料外的错误时候触发回调 $udp->on(\Bobby\Servers\Udp\Server::ERROR_EVENT, function (\Bobby\Servers\Udp\Server $server, Throwable $exception) { echo $exception->getTraceAsString(); });
public function pause()
服务器停止接收连接和读取客户端数据。
public function resume()
服务器回复接收连接和读取数据。
public function sendTo(string $address, string $message): bool
给连接的客户端发送数据。该操作是异步操作,不会产生IO阻塞。
参数:
$address string 发送地址。
$message string 消息。
public function listen()
server开始监听连接。
public function getEventLoop(): Bobby\StreamEventLoop\LoopContract
获取通过构造函数传入的事件循环对象Bobby\StreamEventLoop\LoopContract接口实现类,可用于处理异步逻辑编程,定时器等功能。详见功能见:https://packagist.org/packages/bobby/stream-event-loop
public function getServeSocket(): Bobby\Servers\Contracts\SocketContract
获取Bobby\Servers\Socket对象实例。
示例:
<?php require __DIR__ . "/../vendor/autoload.php"; $loop = \Bobby\StreamEventLoop\LoopFactory::make(); $serveSocket = new \Bobby\Servers\Socket('0.0.0.0:80'); $config = new \Bobby\Servers\ServerConfig(); $udp = new \Bobby\Servers\Udp\Server($serveSocket, $config, $loop); $udp->on(\Bobby\Servers\Udp\Server::RECEIVE_EVENT, function (\Bobby\Servers\Udp\Server $server, $address, string $message) { echo "Receive socket address:$address and data:$message", PHP_EOL; $written = $server->sendTo($address, 'ok!'); echo "Send buffer num $written", PHP_EOL; }); $udp->on(\Bobby\Servers\Udp\Server::ERROR_EVENT, function (\Bobby\Servers\Udp\Server $server, Throwable $exception) { echo $exception->getTraceAsString(); }); $udp->listen(); $loop->poll();