horror/php-wss

支持URI解析和进程支持的Web-socket服务器/客户端

dev-master 2023-07-09 15:04 UTC

This package is not auto-updated.

Last update: 2024-09-16 18:50:26 UTC


README

支持多进程和解析模板的服务器端以及客户端的发送/接收选项的Web-socket服务器/客户端

Scrutinizer Code Quality Build Status Latest Stable Version Total Downloads License: MIT

库包含几个主要选项

服务器

  • 它是一个多连接的WebSocket服务器,具有所有事件的解码/编码(带依赖注入的消息处理器)
  • 它具有GET URI解析器,因此您可以轻松地使用任何模板
  • 每个用户连接支持多个进程,因此您可以将进程进行分支以加快性能,决定有多少客户端连接
  • 向所有客户端广播消息
  • 源检查
  • 运行ssl服务器

客户端

  • 您有握手(默认自动执行)并向服务器发送消息的能力
  • 从服务器接收响应
  • 通过代理启动连接

如何设置?

首选安装方式是使用Composer。

在shell中执行命令

 composer require arthurkushman/php-wss

或者

只需将

"require": {
  "arthurkushman/php-wss": ">=1.3"
}

添加到您的项目的composer.json中。

实现您的WebSocket处理类 - 示例。

<?php
use WSSC\Contracts\ConnectionContract;
use WSSC\Contracts\WebSocket;
use WSSC\Exceptions\WebSocketException;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

class ServerHandler extends WebSocket
{

    /*
     *  if You need to parse URI context like /messanger/chat/JKN324jn4213
     *  You can do so by placing URI parts into an array - $pathParams, when Socket will receive a connection
     *  this variable will be appropriately set to key => value pairs, ex.: ':context' => 'chat'
     *  Otherwise leave $pathParams as an empty array
     */

    public $pathParams = [':entity', ':context', ':token'];
    private $clients = [];

    private $log;

    /**
     * ServerHandler constructor.
     *
     * @throws \Exception
     */
    public function __construct()
    {
        // create a log channel
        $this->log = new Logger('ServerSocket');
        $this->log->pushHandler(new StreamHandler('./tests/tests.log'));
    }

    public function onOpen(ConnectionContract $conn)
    {
        $this->clients[$conn->getUniqueSocketId()] = $conn;
        $this->log->debug('Connection opend, total clients: ' . count($this->clients));
    }

    public function onMessage(ConnectionContract $recv, $msg)
    {
        $this->log->debug('Received message:  ' . $msg);
        $recv->send($msg);
    }

    public function onClose(ConnectionContract $conn)
    {
        unset($this->clients[$conn->getUniqueSocketId()]);
        $this->log->debug('close: ' . print_r($this->clients, 1));
        $conn->close();
    }

    /**
     * @param ConnectionContract $conn
     * @param WebSocketException $ex
     */
    public function onError(ConnectionContract $conn, WebSocketException $ex)
    {
        echo 'Error occured: ' . $ex->printStack();
    }

    /**
     * You may want to implement these methods to bring ping/pong events
     *
     * @param ConnectionContract $conn
     * @param string $msg
     */
    public function onPing(ConnectionContract $conn, $msg)
    {
        // TODO: Implement onPing() method.
    }

    /**
     * @param ConnectionContract $conn
     * @param $msg
     * @return mixed
     */
    public function onPong(ConnectionContract $conn, $msg)
    {
        // TODO: Implement onPong() method.
    }
}

为了保存具有唯一ID的客户端 - 使用getUniqueSocketId(),它返回(类型转换为int)socketConnection资源ID。

然后将下面的代码放入您的CLI/Console脚本中并运行。

<?php
use WSSC\WebSocketServer;
use WSSCTEST\ServerHandler;
use WSSC\Components\ServerConfig;

$config = new ServerConfig();
$config->setClientsPerFork(2500);
$config->setStreamSelectTimeout(2 * 3600);

$webSocketServer = new WebSocketServer(new ServerHandler(), $config);
$webSocketServer->run();

如何设置WebSocket客户端连接?

<?php
use WSSC\WebSocketClient;
use \WSSC\Components\ClientConfig;

$client = new WebSocketClient('ws://:8000/notifications/messanger/yourtoken123', new ClientConfig());
$client->send('{"user_id" : 123}');
echo $client->receive();

就是这样,客户端只是向服务器发送任何文本内容(消息)。

服务器读取所有消息并将它们推送到处理类,以进行进一步的自定义处理。

如何传递可选的超时、标题、片段大小等?

您可以将可选配置传递给WebSocketClient的构造函数,例如。

<?php
use WSSC\WebSocketClient;
use WSSC\Components\ClientConfig;

$config = new ClientConfig();
$config->setFragmentSize(8096);
$config->setTimeout(15);
$config->setHeaders([
    'X-Custom-Header' => 'Foo Bar Baz',
]);

// if proxy settings is of need
$config->setProxy('127.0.0.1', '80');
$config->setProxyAuth('proxyUser', 'proxyPass');

$client = new WebSocketClient('ws://:8000/notifications/messanger/yourtoken123', $config);

如果需要发送ssl请求,只需将wss方案设置为构造函数的url参数中的WebSocketClient - 它将被传递并自动用作ssl。

您还可以为stream_context_create设置特定的上下文选项,以将其提供给stream_socket_client,例如

$config = new ClientConfig();
$config->setContextOptions(['ssl' => ['verify_peer' => false, 'verify_peer_name' => false]]);

或任何其他可用选项,请参阅 - https://php.ac.cn/manual/en/context.php

广播

您可能希望通过在您的ServerHandler类的任何方法中调用broadCast方法来广播消息

$conn->broadCast('hey everybody...');

// or to send multiple messages with 2 sec delay between them
$conn->broadCastMany(['Hello', 'how are you today?', 'have a nice day'], 2);

源检查

为了使服务器检查由n个主机提供的源头

$config = new ServerConfig();
$config->setOrigins(["example.com", "otherexample.com"]);
$websocketServer = new WebSocketServer(new ServerHandler(), $config);
$websocketServer->run();

服务器将自动检查这些主机,即使某些主机未通过检查,也会继续监听其他连接。

SSL服务器运行选项

use WSSC\Components\ServerConfig;
use WSSC\WebSocketServer;

$config = new ServerConfig();
$config->setIsSsl(true)->setAllowSelfSigned(true)
    ->setCryptoType(STREAM_CRYPTO_METHOD_SSLv23_SERVER)
    ->setLocalCert("./tests/certs/cert.pem")->setLocalPk("./tests/certs/key.pem")
    ->setPort(8888);

$websocketServer = new WebSocketServer(new ServerHandler(), $config);
$websocketServer->run();

避免高CPU使用率

use WSSC\WebSocketServer;
use WSSCTEST\ServerHandler;
use WSSC\Components\ServerConfig;

$config = new ServerConfig();

// Set the read socket iteration delay in miliseconds
$config->setLoopingDelay(1);

$webSocketServer = new WebSocketServer(new ServerHandler(), $config);
$webSocketServer->run();

如何测试

要运行服务器 - 从项目的根目录执行

phpunit --bootstrap ./tests/_bootstrap.php ./tests/WebSocketServerTest.php

要运行客户端 - 在另一个控制台中执行

phpunit --bootstrap ./tests/_bootstrap.php ./tests/WebSocketClientTest.php

PHP7支持自版本1.3起 - 具有类型、返回值和更好的函数实现。

基准测试

如您所注意到的,平均发送消息的时间为4.427μs,大约为4微秒,在发送了3次连续的10,000次后。

当进程数量增加,名为 "php-wss" 的进程将会增加,而堆栈大小将会减少。例如,如果设置为100个连接每进程(CPP),并且有128个连接,您将能够看到2个 "php-wss" 进程,例如使用以下命令:ps aux | grep php-wss

使用情况:

alt Avito logo

感谢支持者:

JetBrains logo