loner/stream-stateless

无连接状态的流服务组件,用于构建无连接状态的流服务端及客户端

v1.0.0 2022-04-21 20:34 UTC

This package is auto-updated.

Last update: 2024-05-22 01:02:31 UTC


README

用于构建无连接状态(基于 UDP 协议)的流服务端及客户端

运行依赖

安装

composer require loner/stream-stateless

快速入门

  • UDP 服务端

    #!/usr/bin/env php
    <?php
    
    declare(strict_types=1);
    
    use Loner\Reactor\Builder;
    use Loner\Stream\Event\{Start, Stop};
    use Loner\Stream\Stateless\{Event\Accept, Server\UdpServer, ServerEvent};
    
    // composer 自加载
    require_once __DIR__ . '/../vendor/autoload.php';
    
    // 事件轮询反应器
    $reactor = Builder::create();
    
    // 创建服务端:事件轮询反应器、主机名、端口号、绑定上下文配置(默认空数组)、是否端口复用(默认 Linux >= 3.9)
    $server = new UdpServer($reactor, '0.0.0.0', 6957);
    
    // 绑定事件响应
    $server
        // 服务器启动(创建监听网络后、进入事件循环前)
        ->on(ServerEvent::Start, function (Start $event) {
            echo sprintf('Start: %s', $event->server->getSocketAddress()), PHP_EOL;
        })
        // 服务器停止(移除监听网络后、破坏事件循环前)
        ->on(ServerEvent::Stop, function (Stop $event) {
            echo sprintf('Stop: %s', $event->server->getSocketAddress()), PHP_EOL;
        })
        // 收到远程消息
        ->on(ServerEvent::Accept, function (Accept $event) {
            echo sprintf('Accept: %s => %s', $event->remoteAddress, $event->message), PHP_EOL;
            $event->server->send('Hi. I\'m the server.', $event->remoteAddress);
        });
    
    // 启动服务器
    $server->start();
  • UDP 客户端

    #!/usr/bin/env php
    <?php
    
    declare(strict_types=1);
    
    use Loner\Reactor\Builder;
    use Loner\Stream\Event\OpenFail;
    use Loner\Stream\Stateless\{Client\UdpClient, ClientEvent, Event\Close, Event\Open, Event\Receive};
    
    // composer 自加载
    require_once __DIR__ . '/../vendor/autoload.php';
    
    // 事件轮询反应器
    $reactor = Builder::create();
    
    // 创建客户端:事件轮询反应器、主机名、端口号、绑定上下文配置(默认空数组)
    $client = new UdpClient($reactor, '127.0.0.1', 6957);
    
    // 绑定事件响应
    $client
        // 开启通信网络失败
        ->on(ClientEvent::OpenFail, function (OpenFail $event) {
            echo sprintf('OpenFail:%s => [%d] [%s]', $event->client->getSocketAddress(), $event->code, $event->message), PHP_EOL;
        })
        // 通信网络已开启
        ->on(ClientEvent::Open, function (Open $event) {
            $client = $event->client;
            echo sprintf('Open: %s', $client->getSocketAddress()), PHP_EOL;
            $client->send('Hi. I\'m a client.');
            $client->send('Hi. I\'m a client.');
            $client->send('Hi. I\'m a client.');
            $client->send('Hi. I\'m a client.');
            $client->send('Hi. I\'m a client.');
        })
        // 收到服务端消息
        ->on(ClientEvent::Receive, function (Receive $event) {
            $client = $event->client;
            echo sprintf('Receive: %s', $event->message), PHP_EOL;
            static $requestTimes = 0;
            if (++$requestTimes === 5) {
                $client->close();
            }
        })
        // 通信网络已关闭
        ->on(ClientEvent::Close, function (Close $event) {
            echo sprintf('Close: %s', $event->client->getSocketAddress()), PHP_EOL;
        });
    
    // 监听网络
    $client->listen();
    
    // 进入事件轮询
    $reactor->loop();

组件功能说明

继承【流服务基础组件】功能,详见【 loner/stream

补充说明:

  • UDP 服务端:Loner\Stream\Stateless\Server\UdpServer

    use Loner\Stream\Event\{Start, Stop};
    use Loner\Stream\Stateless\{Event\Accept, Server\UdpServer, ServerEvent};
    
    /** @var UdpServer $server */
    
    // 监听主机地址
    $host = $server->getHost();
    // 监听端口号
    $port = $server->getPort();
    
    // 是否端口复用
    $reusable = $server->reusable();
    // 绑定上下文端口复用设置
    $server->reusePort();
    
    // 绑定事件响应
    // $server->on(ServerEvent $event, ?callable $listener): static;
    $server
        // 服务器启动(创建监听网络后、进入事件循环前)
        ->on(ServerEvent::Start, function (Start $event): void {
            // 当前服务端
            $server = $event->server;
    
            // 业务代码
        })
        // 服务器停止(移除监听网络后、破坏事件循环之前)
        ->on(ServerEvent::Stop, function (Stop $event): void {
            // 当前服务端
            $server = $event->server;
    
            // 业务代码
        })
        // 收到远程消息
        ->on(ServerEvent::Accept, function (Accept $event): void {
            // 当前服务端
            $server = $event->server;
            /** @var Stringable|string $message 有应用层协议时,为消息实体;否则为接收数据字符串 */
            $message = $event->message;
            // 消息来源地址
            $remoteAddress = $event->remoteAddress;
    
            // 业务代码
        });
    
    /** @var string $remoteAddress */
    /** @var string $package */
    /** @var Stringable $message */
    
    // 发送消息到指定地址
    // 1. 常规方式
    $server->send($package, $remoteAddress);
    // 2. 存在应用层协议
    $server->send($message, $remoteAddress);
    $server->send((string)$message, $remoteAddress);
  • UDP 客户端:Loner\Stream\Stateless\Client\UdpClient

    use Loner\Stream\Event\OpenFail;
    use Loner\Stream\Stateless\Event\{Close, Open, Receive};
    use Loner\Stream\Stateless\{Client\UdpClient, ClientEvent};
    
    /** @var UdpClient $client */
    
    // 获取监听主机地址
    $host = $client->getHost();
    // 获取监听端口号
    $port = $client->getPort();
    
    // 返回本地地址
    $client->getLocalAddress();
    // 返回远程(服务端)地址
    $client->getRemoteAddress();
    
    // 绑定事件响应
    // $client->on(ServerEvent $event, ?callable $listener): static;
    $client
        // 开启通信网络失败
        ->on(ClientEvent::OpenFail, function (OpenFail $event): void {
            // 当前客户端
            $client = $event->client;
            // 错误信息
            $message = $event->message;
            // 错误码
            $code = $event->code;
    
            // 业务代码
        })
        // 通信网络已开启
        ->on(ClientEvent::Open, function (Open $event): void {
            // 当前客户端
            $client = $event->client;
    
            // 业务代码
        })
        // 收到服务端消息
        ->on(ClientEvent::Receive, function (Receive $event): void {
            // 当前客户端
            $client = $event->client;
            /** @var Stringable|string $message 有应用层协议时,为消息实体;否则为接收数据字符串 */
            $message = $event->message;
    
            // 业务代码
        })
        // 通信网络已关闭
        ->on(ClientEvent::Close, function (Close $event): void {
            // 当前客户端
            $client = $event->client;
    
            // 业务代码
        });
    
    /** @var string $package */
    /** @var Stringable $message */
    /** @var string $remoteAddress */
    
    // 发送消息到服务端
    // 1. 常规方式
    $client->send($package);
    // 2. 存在应用层协议
    $client->send($message);
    $client->send((string)$message);
    
    // 发送消息到指定地址(当指定第二个参数时)
    $client->send($package, $remoteAddress);
    $client->send($message, $remoteAddress);
    $client->send((string)$message, $remoteAddress);
    
    // 关闭客户端
    // 1. 直接关闭
    $client->close();
    // 2. 发送消息到服务端后关闭
    $client->close($package);
    $client->close($message);
    $client->close((string)$message);
    // 3. 发送消息到指定地址后关闭
    $client->close($package, $remoteAddress);
    $client->close($message, $remoteAddress);
    $client->close((string)$message, $remoteAddress);