horror / php-wss
支持URI解析和进程支持的Web-socket服务器/客户端
Requires
- php: >=7.4
Requires (Dev)
- monolog/monolog: ^1.24
- phpbench/phpbench: ^1.2
- phpstan/phpstan: ^1.4
- phpunit/phpunit: ^9
Suggests
- ext-pcntl: Allows for forking the server process to handle more clients at once
This package is not auto-updated.
Last update: 2024-09-16 18:50:26 UTC
README
支持多进程和解析模板的服务器端以及客户端的发送/接收选项的Web-socket服务器/客户端
库包含几个主要选项
服务器
- 它是一个多连接的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
使用情况:
感谢支持者: