{"id":13405222,"url":"https://github.com/arthurkushman/php-wss","last_synced_at":"2025-05-16T18:10:36.662Z","repository":{"id":37820097,"uuid":"47051936","full_name":"arthurkushman/php-wss","owner":"arthurkushman","description":"Web-socket server/client with multi-process and parse templates support  on server and send/receive options on client","archived":false,"fork":false,"pushed_at":"2023-10-26T21:13:49.000Z","size":209,"stargazers_count":213,"open_issues_count":8,"forks_count":32,"subscribers_count":16,"default_branch":"master","last_synced_at":"2025-04-12T17:46:25.172Z","etag":null,"topics":["multi-process","php","processes","routes","websocket","websocket-client","websocket-server","websockets"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arthurkushman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null},"funding":{"liberapay":"arthurkushman","issuehunt":"arthurkushman","patreon":"user?u=26175584"}},"created_at":"2015-11-29T05:56:09.000Z","updated_at":"2025-01-23T14:31:53.000Z","dependencies_parsed_at":"2024-01-18T23:04:51.682Z","dependency_job_id":"a13ca665-6dc9-436a-85e6-70e80af67c7b","html_url":"https://github.com/arthurkushman/php-wss","commit_stats":{"total_commits":135,"total_committers":8,"mean_commits":16.875,"dds":"0.24444444444444446","last_synced_commit":"f04fa59311cab0fe2e406878b4a167227ac50993"},"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arthurkushman%2Fphp-wss","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arthurkushman%2Fphp-wss/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arthurkushman%2Fphp-wss/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arthurkushman%2Fphp-wss/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arthurkushman","download_url":"https://codeload.github.com/arthurkushman/php-wss/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254274725,"owners_count":22043573,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["multi-process","php","processes","routes","websocket","websocket-client","websocket-server","websockets"],"created_at":"2024-07-30T19:01:57.533Z","updated_at":"2025-05-16T18:10:36.641Z","avatar_url":"https://github.com/arthurkushman.png","language":"PHP","funding_links":["https://liberapay.com/arthurkushman","https://issuehunt.io/r/arthurkushman","https://patreon.com/user?u=26175584"],"categories":["PHP"],"sub_categories":[],"readme":"# php-wss\nWeb-socket server/client with multi-process and parse templates support on server and send/receive options on client\n\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/arthurkushman/php-wss/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/arthurkushman/php-wss/?branch=master)\n[![Build Status](https://scrutinizer-ci.com/g/arthurkushman/php-wss/badges/build.png?b=master)](https://scrutinizer-ci.com/g/arthurkushman/php-wss/build-status/master)\n[![Latest Stable Version](https://poser.pugx.org/arthurkushman/php-wss/v/stable)](https://packagist.org/packages/arthurkushman/php-wss)\n[![Total Downloads](https://poser.pugx.org/arthurkushman/php-wss/downloads)](https://packagist.org/packages/arthurkushman/php-wss)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n\n## Library comes with several main options\nServer:\n- it`s a web-socket server for multiple connections with decoding/encoding for all events out of the box (with Dependency Injected MessageHandler)\n- it has GET uri parser, so you can easily use any templates\n- multiple process per user connections support, so you can fork processes to speed up performance deciding how many client-connections should be there\n- broadcasting message(s) to all clients\n- origin check\n- ssl server run\n\nClient:\n- You have the ability to handshake (which is performed automatically) and send messages to server\n- Receive a response from the server\n- Initiate connection via proxy\n\n## How do I get set up?\n\nPreferred way to install is with Composer.\n\nperform command in shell\n\n```bash\n composer require arthurkushman/php-wss\n```\n\nOR\n\njust add\n\n```javascript\n\"require\": {\n  \"arthurkushman/php-wss\": \"\u003e=1.3\"\n}\n```\n\nto your projects composer.json.\n\n### Implement your WebSocket handler class - ex.:\n\n```php\n\u003c?php\nuse WSSC\\Contracts\\ConnectionContract;\nuse WSSC\\Contracts\\WebSocket;\nuse WSSC\\Exceptions\\WebSocketException;\nuse Monolog\\Logger;\nuse Monolog\\Handler\\StreamHandler;\n\nclass ServerHandler extends WebSocket\n{\n\n    /*\n     *  if You need to parse URI context like /messanger/chat/JKN324jn4213\n     *  You can do so by placing URI parts into an array - $pathParams, when Socket will receive a connection\n     *  this variable will be appropriately set to key =\u003e value pairs, ex.: ':context' =\u003e 'chat'\n     *  Otherwise leave $pathParams as an empty array\n     */\n\n    public $pathParams = [':entity', ':context', ':token'];\n    private $clients = [];\n\n    private $log;\n\n    /**\n     * ServerHandler constructor.\n     *\n     * @throws \\Exception\n     */\n    public function __construct()\n    {\n        // create a log channel\n        $this-\u003elog = new Logger('ServerSocket');\n        $this-\u003elog-\u003epushHandler(new StreamHandler('./tests/tests.log'));\n    }\n\n    public function onOpen(ConnectionContract $conn)\n    {\n        $this-\u003eclients[$conn-\u003egetUniqueSocketId()] = $conn;\n        $this-\u003elog-\u003edebug('Connection opend, total clients: ' . count($this-\u003eclients));\n    }\n\n    public function onMessage(ConnectionContract $recv, $msg)\n    {\n        $this-\u003elog-\u003edebug('Received message:  ' . $msg);\n        $recv-\u003esend($msg);\n    }\n\n    public function onClose(ConnectionContract $conn)\n    {\n        unset($this-\u003eclients[$conn-\u003egetUniqueSocketId()]);\n        $this-\u003elog-\u003edebug('close: ' . print_r($this-\u003eclients, 1));\n        $conn-\u003eclose();\n    }\n\n    /**\n     * @param ConnectionContract $conn\n     * @param WebSocketException $ex\n     */\n    public function onError(ConnectionContract $conn, WebSocketException $ex)\n    {\n        echo 'Error occured: ' . $ex-\u003eprintStack();\n    }\n\n    /**\n     * You may want to implement these methods to bring ping/pong events\n     *\n     * @param ConnectionContract $conn\n     * @param string $msg\n     */\n    public function onPing(ConnectionContract $conn, $msg)\n    {\n        // TODO: Implement onPing() method.\n    }\n\n    /**\n     * @param ConnectionContract $conn\n     * @param $msg\n     * @return mixed\n     */\n    public function onPong(ConnectionContract $conn, $msg)\n    {\n        // TODO: Implement onPong() method.\n    }\n}\n\n```\nTo save clients with their unique ids - use `getUniqueSocketId()` which returns (type-casted to int) socketConnection resource id.\n\n### Then put code bellow to Your CLI/Console script and run\n\n```php\n\u003c?php\nuse WSSC\\WebSocketServer;\nuse WSSCTEST\\ServerHandler;\nuse WSSC\\Components\\ServerConfig;\n\n$config = new ServerConfig();\n$config-\u003esetClientsPerFork(2500);\n$config-\u003esetStreamSelectTimeout(2 * 3600);\n\n$webSocketServer = new WebSocketServer(new ServerHandler(), $config);\n$webSocketServer-\u003erun();\n```\n\n### How do I set WebSocket Client connection?\n\n```php\n\u003c?php\nuse WSSC\\WebSocketClient;\nuse \\WSSC\\Components\\ClientConfig;\n\n$client = new WebSocketClient('ws://localhost:8000/notifications/messanger/yourtoken123', new ClientConfig());\n$client-\u003esend('{\"user_id\" : 123}');\necho $client-\u003ereceive();\n```\n\nThat`s it, client is just sending any text content (message) to the Server.\n\nServer reads all the messages and push them to Handler class, for further custom processing.\n\n### How to pass an optional timeout, headers, fragment size etc?\nYou can pass optional configuration to `WebSocketClient`'s constructor e.g.:\n```php\n\u003c?php\nuse WSSC\\WebSocketClient;\nuse WSSC\\Components\\ClientConfig;\n\n$config = new ClientConfig();\n$config-\u003esetFragmentSize(8096);\n$config-\u003esetTimeout(15);\n$config-\u003esetHeaders([\n    'X-Custom-Header' =\u003e 'Foo Bar Baz',\n]);\n\n// if proxy settings is of need\n$config-\u003esetProxy('127.0.0.1', '80');\n$config-\u003esetProxyAuth('proxyUser', 'proxyPass');\n\n$client = new WebSocketClient('ws://localhost:8000/notifications/messanger/yourtoken123', $config);\n```\nIf it is of need to send ssl requests just set `wss` scheme to constructors url param of `WebSocketClient` - it will be passed and used as ssl automatically.\n\nYou can also set particular context options for `stream_context_create` to provide them to `stream_socket_client`, for instance:\n```php\n$config = new ClientConfig();\n$config-\u003esetContextOptions(['ssl' =\u003e ['verify_peer' =\u003e false, 'verify_peer_name' =\u003e false]]);\n```\nor any other available options see - https://www.php.net/manual/en/context.php.\n\n### BroadCasting\nYou may wish to broadcast messages by simply calling `broadCast` method on `Connection` object in any method of your `ServerHandler` class:\n```php\n$conn-\u003ebroadCast('hey everybody...');\n\n// or to send multiple messages with 2 sec delay between them\n$conn-\u003ebroadCastMany(['Hello', 'how are you today?', 'have a nice day'], 2);\n```\n\n### Origin check\nTo let server check the Origin header with `n` hosts provided:\n```php\n$config = new ServerConfig();\n$config-\u003esetOrigins([\"example.com\", \"otherexample.com\"]);\n$websocketServer = new WebSocketServer(new ServerHandler(), $config);\n$websocketServer-\u003erun();\n```\nServer will automatically check those hosts proceeding to listen for other connections even if some failed to pass check.\n\n### SSL Server run options\n```php\nuse WSSC\\Components\\ServerConfig;\nuse WSSC\\WebSocketServer;\n\n$config = new ServerConfig();\n$config-\u003esetIsSsl(true)-\u003esetAllowSelfSigned(true)\n    -\u003esetCryptoType(STREAM_CRYPTO_METHOD_SSLv23_SERVER)\n    -\u003esetLocalCert(\"./tests/certs/cert.pem\")-\u003esetLocalPk(\"./tests/certs/key.pem\")\n    -\u003esetPort(8888);\n\n$websocketServer = new WebSocketServer(new ServerHandler(), $config);\n$websocketServer-\u003erun();\n```\n\n### Avoid high CPU usage\n```php\nuse WSSC\\WebSocketServer;\nuse WSSCTEST\\ServerHandler;\nuse WSSC\\Components\\ServerConfig;\n\n$config = new ServerConfig();\n\n// Set the read socket iteration delay in miliseconds\n$config-\u003esetLoopingDelay(1);\n\n$webSocketServer = new WebSocketServer(new ServerHandler(), $config);\n$webSocketServer-\u003erun();\n```\n\n### How to test\n\nTo run the Server - execute from the root of a project:\n```php\nphpunit --bootstrap ./tests/_bootstrap.php ./tests/WebSocketServerTest.php\n```\n\nTo run the Client - execute in another console:\n```php\nphpunit --bootstrap ./tests/_bootstrap.php ./tests/WebSocketClientTest.php\n```\n\nPHP7 support since version 1.3 - with types, returns and better function implementations.\n\nBenchmarks:\n\n\n| iter | benchmark           | subject      | set | revs  | mem_peak   | time_avg | comp_z_value | comp_deviation |\n| ---  | ---                 | ---          | --- |  ---  |   ---      |   ---    |    ---       |      ---       |\n| 0    | MaxConnectionsBench | benchConnect |     | 10000 | 1,547,496b | 4.831μs  | +1.41σ       | +6.35%         |\n| 1    | MaxConnectionsBench | benchConnect |     | 10000 | 1,547,496b | 4.372μs  | -0.83σ       | -3.76%         |\n| 2    | MaxConnectionsBench | benchConnect |     | 10000 | 1,547,496b | 4.425μs  | -0.57σ       | -2.59%         |\n\n\n| benchmark           | subject      | revs  | its | mem_peak | mode    | rstdev |\n|   ---               | ---          | ---   | --- |  ---     | ---     | ---    |\n| MaxConnectionsBench | benchConnect | 10000 | 3   | 1.547mb  | 4.427μs | ±4.51% |\n\nAs you may have been noticed, average time to send msg is `4.427μs` which is roughly rounded to `4` microseconds \nwithin 10 000 have been sent 3 times in a row.\n\nPS U'll see the processes increase named \"php-wss\" as CPP (Connections Per-Process) will grow and decrease while stack will lessen.\nFor instance, if set 100 CPP and there are 128 connections - You will be able to see 2 \"php-wss\" processes with for ex.: `ps aux | grep php-wss`\n\nUsed by:\n\n![alt Avito logo](https://github.com/SoliDry/laravel-api/blob/master/tests/images/avito_logo.png)\n\nSupporters gratitude:\n\n\u003cimg src=\"https://github.com/SoliDry/laravel-api/blob/master/tests/images/jetbrains-logo.png\" alt=\"JetBrains logo\" width=\"200\" height=\"166\" /\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farthurkushman%2Fphp-wss","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farthurkushman%2Fphp-wss","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farthurkushman%2Fphp-wss/lists"}