{"id":24694466,"url":"https://github.com/roadrunner-php/tcp","last_synced_at":"2025-06-14T02:32:49.602Z","repository":{"id":45656742,"uuid":"421732201","full_name":"roadrunner-php/tcp","owner":"roadrunner-php","description":"🔌 TCP Worker Client for RoadRunner application server","archived":false,"fork":false,"pushed_at":"2024-04-12T08:38:28.000Z","size":42,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"4.x","last_synced_at":"2025-01-22T22:15:45.298Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":false,"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/roadrunner-php.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null},"funding":{"github":"roadrunner-server"}},"created_at":"2021-10-27T08:13:57.000Z","updated_at":"2024-02-28T16:14:02.000Z","dependencies_parsed_at":"2024-02-07T21:33:56.368Z","dependency_job_id":"3d390ba1-642e-4b16-ae7f-de12d695e561","html_url":"https://github.com/roadrunner-php/tcp","commit_stats":null,"previous_names":["spiral/roadrunner-tcp"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roadrunner-php%2Ftcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roadrunner-php%2Ftcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roadrunner-php%2Ftcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/roadrunner-php%2Ftcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/roadrunner-php","download_url":"https://codeload.github.com/roadrunner-php/tcp/tar.gz/refs/heads/4.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235781133,"owners_count":19043931,"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":[],"created_at":"2025-01-26T23:59:48.781Z","updated_at":"2025-01-26T23:59:49.231Z","avatar_url":"https://github.com/roadrunner-php.png","language":"PHP","funding_links":["https://github.com/sponsors/roadrunner-server"],"categories":[],"sub_categories":[],"readme":"\u003ca href=\"https://roadrunner.dev\" target=\"_blank\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://github.com/roadrunner-server/.github/assets/8040338/e6bde856-4ec6-4a52-bd5b-bfe78736c1ff\"\u003e\n    \u003cimg align=\"center\" src=\"https://github.com/roadrunner-server/.github/assets/8040338/040fb694-1dd3-4865-9d29-8e0748c2c8b8\"\u003e\n  \u003c/picture\u003e\n\u003c/a\u003e\n\n# RoadRunner TCP Plugin\n\n[![PHP Version Require](https://poser.pugx.org/spiral/roadrunner-tcp/require/php)](https://packagist.org/packages/spiral/roadrunner-tcp)\n[![Latest Stable Version](https://poser.pugx.org/spiral/roadrunner-tcp/v/stable)](https://packagist.org/packages/spiral/roadrunner-tcp)\n[![phpunit](https://github.com/spiral/roadrunner-tcp/actions/workflows/phpunit.yml/badge.svg)](https://github.com/spiral/roadrunner-tcp/actions)\n[![psalm](https://github.com/spiral/roadrunner-tcp/actions/workflows/psalm.yml/badge.svg)](https://github.com/spiral/roadrunner-tcp/actions)\n[![Codecov](https://codecov.io/gh/roadrunner-php/tcp/branch/4.x/graph/badge.svg)](https://codecov.io/gh/roadrunner-php/tcp)\n[![Total Downloads](https://poser.pugx.org/spiral/roadrunner-tcp/downloads)](https://packagist.org/packages/spiral/roadrunner-tcp)\n[![type-coverage](https://shepherd.dev/github/roadrunner-php/tcp/coverage.svg)](https://shepherd.dev/github/spiral/roadrunner-php/tcp)\n[![psalm-level](https://shepherd.dev/github/roadrunner-php/tcp/level.svg)](https://shepherd.dev/github/roadrunner-php/tcp)\n\nRoadRunner is an open-source (MIT licensed) high-performance PHP application server, load balancer, and process manager.\nIt supports running as a service with the ability to extend its functionality on a per-project basis.\n\nRoadRunner includes TCP server and can be used to replace classic TCP setup with much greater performance and flexibility.\n\n\u003cp align=\"center\"\u003e\n\t\u003ca href=\"https://roadrunner.dev/\"\u003e\u003cb\u003eOfficial Website\u003c/b\u003e\u003c/a\u003e | \n\t\u003ca href=\"https://docs.roadrunner.dev\"\u003e\u003cb\u003eDocumentation\u003c/b\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nThis repository contains the codebase TCP PHP workers. Check [spiral/roadrunner](https://github.com/spiral/roadrunner)\nto get application server.\n\n## Installation\n\nTo install application server and TCP codebase:\n\n```bash\ncomposer require spiral/roadrunner-tcp\n```\n\nYou can use the convenient installer to download the latest available compatible version of RoadRunner assembly:\n\n```bash\ncomposer require spiral/roadrunner-cli --dev\n```\n\nTo download latest version of application server:\n\n```bash\nvendor/bin/rr get\n```\n\n## Usage\n\nFor example, such a configuration would be quite feasible to run:\n\n```yaml\ntcp:\n  servers:\n    smtp:\n      addr: tcp://127.0.0.1:1025\n      delimiter: \"\\r\\n\" # by default\n    server2:\n      addr: tcp://127.0.0.1:8889\n\n  pool:\n    num_workers: 2\n    max_jobs: 0\n    allocate_timeout: 60s\n    destroy_timeout: 60s\n```\n\nIf you have more than 1 worker in your pool TCP server will send received packets to different workers,\nand if you need to collect data you have to use storage, that can be accessed by all workers, for example [RoadRunner Key Value](https://github.com/spiral/roadrunner-kv)\n\n### Example\n\nTo init abstract RoadRunner worker:\n\n```php\n\u003c?php\n\nrequire __DIR__ . '/vendor/autoload.php';\n\nuse Spiral\\RoadRunner\\Worker;\nuse Spiral\\RoadRunner\\Tcp\\TcpWorker;\nuse Spiral\\RoadRunner\\Tcp\\TcpResponse;\nuse Spiral\\RoadRunner\\Tcp\\TcpEvent;\n\n// Create new RoadRunner worker from global environment\n$worker = Worker::create();\n\n$tcpWorker = new TcpWorker($worker);\n\nwhile ($request = $tcpWorker-\u003ewaitRequest()) {\n\n    try {\n        if ($request-\u003egetEvent() === TcpEvent::Connected) {\n            // You can close connection according your restrictions\n            if ($request-\u003egetRemoteAddress() !== '127.0.0.1') {\n                $tcpWorker-\u003eclose();\n                continue;\n            }\n            \n            // -----------------\n            \n            // Or continue read data from server\n            // By default, server closes connection if a worker doesn't send CONTINUE response \n            $tcpWorker-\u003eread();\n            \n            // -----------------\n            \n            // Or send response to the TCP connection, for example, to the SMTP client\n            $tcpWorker-\u003erespond(\"220 mailamie \\r\\n\");\n            \n        } elseif ($request-\u003egetEvent() === TcpEvent::Data) {\n                   \n            $body = $request-\u003egetBody();\n            \n            // ... handle request from TCP server [tcp_access_point_1]\n            if ($request-\u003egetServer() === 'tcp_access_point_1') {\n\n                // Send response and close connection\n                $tcpWorker-\u003erespond('Access denied', TcpResponse::RespondClose);\n               \n            // ... handle request from TCP server [server2] \n            } elseif ($request-\u003egetServer() === 'server2') {\n                \n                // Send response to the TCP connection and wait for the next request\n                $tcpWorker-\u003erespond(\\json_encode([\n                    'remote_addr' =\u003e $request-\u003egetRemoteAddress(),\n                    'server' =\u003e $request-\u003egetServer(),\n                    'uuid' =\u003e $request-\u003egetConnectionUuid(),\n                    'body' =\u003e $request-\u003egetBody(),\n                    'event' =\u003e $request-\u003egetEvent()\n                ]));\n            }\n           \n        // Handle closed connection event \n        } elseif ($request-\u003egetEvent() === TcpEvent::Close) {\n            // Do something ...\n            \n            // You don't need to send response on closed connection\n        }\n        \n    } catch (\\Throwable $e) {\n        $tcpWorker-\u003erespond(\"Something went wrong\\r\\n\", TcpResponse::RespondClose);\n        $worker-\u003eerror((string)$e);\n    }\n}\n```\n\n\u003ca href=\"https://spiral.dev/\"\u003e\n\u003cimg src=\"https://user-images.githubusercontent.com/773481/220979012-e67b74b5-3db1-41b7-bdb0-8a042587dedc.jpg\" alt=\"try Spiral Framework\" /\u003e\n\u003c/a\u003e\n\n## Testing:\n\nThis codebase is automatically tested via host repository - [spiral/roadrunner](https://github.com/spiral/roadrunner).\n\n## License:\n\nThe MIT License (MIT). Please see [`LICENSE`](./LICENSE) for more information. Maintained\nby [Spiral Scout](https://spiralscout.com).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froadrunner-php%2Ftcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Froadrunner-php%2Ftcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Froadrunner-php%2Ftcp/lists"}