# PHPSocket.IO **Repository Path**: FEIGE/phpsocket.io ## Basic Information - **Project Name**: PHPSocket.IO - **Description**: 基于workerman实现的PHPSocket.IO服务器 - **Primary Language**: PHP - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-15 - **Last Updated**: 2026-05-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: socketio, PHP ## README # PHPSocket.IO A PHP server implementation of [Socket.IO](https://socket.io), supporting WebSocket and Long-Polling transports, fully compatible with Socket.IO protocol v4. A high-performance, production-grade Socket.IO server built on Workerman, optimized for PHP environments. ## Features - **Multiple Transport Protocols**: Supports WebSocket and HTTP Long-Polling (multi-process mode only supports WebSocket and requires explicit usage) - **Binary Data Support**: Supports binary event transmission - **Cluster Support**: Multi-process cluster communication via Channel or Redis - **Room Management**: Supports Room management functionality - **Namespaces**: Supports multiple namespaces, recommended to use $io->of() method - **Event Acknowledgement (ACK)**: Supports bidirectional ACK confirmation, requires callback for responses - **Three-Layer Middleware System**: Supports global, namespace-level, and Socket instance-level middleware - **Connection Recovery**: Full support for Socket.IO v4 connection state recovery (private id, offset tracking, state recovery) - **Heartbeat Detection**: Automatic heartbeat keep-alive mechanism - **PSR-3 Logging System**: Supports PSR-3 standard logging interface - **PHP 8.1+ Optimized Implementation**: Uses PHP 8.1 latest features, performance optimized ## System Requirements - PHP >= 8.1 - Workerman >= 4.0 - psr/log >= 3.0 - Optional dependencies: - workerman/channel (required when using ClusterAdapter) - workerman/redis (required when using RedisAdapter) ## Installation ### Using Composer (Recommended) ```bash composer require fage1151/socketio ``` ### Clone from GitHub ```bash # Clone the project git clone https://github.com/phpsocketio/socket.io.git # Enter project directory cd socket.io # Install dependencies composer install ``` ### Install Optional Dependencies #### When using ClusterAdapter: ClusterAdapter is based on Workerman Channel, not included by default, needs to be installed: ```bash composer require workerman/channel ``` #### When using RedisAdapter: ```bash composer require workerman/redis ``` ## Project Structure ``` ├── src/ # Core source directory │ ├── Adapter/ # Adapter directory │ │ ├── AdapterInterface.php # Adapter interface (includes cross-process methods) │ │ ├── ClusterAdapter.php # Channel-based cluster adapter │ │ └── RedisAdapter.php # Redis-based cluster adapter │ ├── Protocol/ # Protocol related │ │ ├── PacketParser.php # Packet parser │ │ ├── PacketDispatcher.php # Packet dispatcher │ │ └── EngineIOHandler.php # Engine.IO protocol handler │ ├── Transport/ # Transport layer │ │ ├── AbstractTransportHandler.php # Base transport class │ │ ├── WebSocketHandler.php # WebSocket handler │ │ ├── PollingHandler.php # Polling handler │ │ └── ConnectionManager.php # Connection manager │ ├── Room/ # Room management │ │ └── RoomManager.php # Room manager │ ├── Event/ # Event system │ │ ├── EventHandler.php # Event handler │ │ └── AckManager.php # ACK callback manager │ ├── Session/ # Session related │ │ ├── SessionStore.php # Session storage manager │ │ └── RecoveryManager.php # Connection state recovery manager │ ├── Enum/ # Enum types │ │ ├── EnginePacketType.php # Engine.IO packet type enum │ │ ├── SocketPacketType.php # Socket.IO packet type enum │ │ └── LogLevelPriority.php # Log level priority enum │ ├── Exceptions/ # Exception classes │ │ └── SocketIOException.php # Socket.IO unified exception │ ├── Support/ # Support classes │ │ ├── Logger.php # PSR-3 compatible logger │ │ ├── ErrorHandler.php # Error handler │ │ ├── Set.php # Set data structure │ │ ├── ServerConfig.php # Server config class, manages configuration │ │ ├── ServerBuilder.php # Server builder, fluent API for easy server creation │ │ └── ServerManager.php # Server manager │ ├── SocketIOServer.php # Socket.IO server main class │ ├── Socket.php # Socket class │ ├── SocketEventEmitter.php # Socket event emitter Trait │ ├── SocketNamespace.php # Namespace handler class │ ├── Session.php # Session management │ └── Broadcaster.php # Unified broadcaster ├── examples/ # Examples directory │ └── server.php # Complete server example ├── docs/ # Documentation directory │ ├── API.md # API reference │ └── USAGE.md # Detailed usage documentation ├── tests/ # Tests directory ├── README.md # Project documentation (Chinese) ├── README.en.md # Project documentation (English) ├── composer.json # Composer configuration ├── phpstan.neon # PHPStan configuration ├── phpcs.xml # PHPCS configuration └── LICENSE # License file ``` ## Core File Descriptions ### Core Classes (Root Directory) - **src/SocketIOServer.php**:Socket.IO server main class, handles connections and event dispatch - **src/SocketNamespace.php**:Namespace handler class, accessed via $io->of() - **src/Session.php**:Session management, manages client session state and connection recovery - **src/Socket.php**:Socket class, encapsulates client connection interface - **src/SocketEventEmitter.php**:Socket event emitter Trait, encapsulates socket event handling functionality - **src/Broadcaster.php**:Unified broadcaster, responsible for message broadcasting ### Protocol Related (Protocol/) - **src/Protocol/PacketParser.php**:Packet parser, parses and constructs Socket.IO packets (uses static map optimization) - **src/Protocol/PacketDispatcher.php**:Packet dispatcher, distributes Socket.IO packets - **src/Protocol/EngineIOHandler.php**:Engine.IO protocol handler, handles underlying transport protocol (decoupled using callbacks) ### Transport Layer (Transport/) - **src/Transport/AbstractTransportHandler.php**:Base transport class with common IP extraction and handshake data building - **src/Transport/WebSocketHandler.php**:WebSocket handler, handles HTTP polling and WebSocket handshake - **src/Transport/PollingHandler.php**:Polling handler - **src/Transport/ConnectionManager.php**:Connection manager ### Room Management (Room/) - **src/Room/RoomManager.php**:Room manager, handles room-related operations ### Event System (Event/) - **src/Event/EventHandler.php**:Event handler, handles various Socket.IO events - **src/Event/AckManager.php**:ACK callback manager, manages all ACK callbacks ### Adapters (Adapter/) - **src/Adapter/AdapterInterface.php**:Adapter interface, defines cross-process communication standards - **src/Adapter/RedisAdapter.php**:Redis adapter, supports cross-process room and session management - **src/Adapter/ClusterAdapter.php**:Channel adapter, supports cross-process room and session management #### AdapterInterface Cross-Process Methods | Method | Description | |--------|-------------| | `allSockets(array $rooms = [])` | Get all connected Socket ID sets (cross-process) | | `fetchSockets(array $rooms = [])` | Get all Socket instance information (cross-process) | | `socketsJoin(string\|array $rooms, array $targetSockets = [])` | Make specified Sockets join rooms (cross-process) | | `socketsLeave(string\|array $rooms, array $targetSockets = [])` | Make specified Sockets leave rooms (cross-process) | | `disconnectSockets(bool $close = false, array $targetSockets = [])` | Disconnect specified Sockets (cross-process) | | `serverSideEmit(string $eventName, array $args = [], ?callable $ack = null)` | Send messages to other servers in the cluster | ### Enum Types (Enum/) - **src/Enum/EnginePacketType.php**:Engine.IO packet type enum - **src/Enum/SocketPacketType.php**:Socket.IO packet type enum - **src/Enum/LogLevelPriority.php**:Log level priority enum ### Exception Classes (Exceptions/) - **src/Exceptions/SocketIOException.php**:Socket.IO unified exception (provides static factory methods to create different exception types) ### Session Related (Session/) - **src/Session/SessionStore.php**:Session storage manager, specifically manages session storage and cache - **src/Session/RecoveryManager.php**:Connection state recovery manager, handles reconnection state recovery ### Support Classes (Support/) - **src/Support/Logger.php**:PSR-3 compatible logger - **src/Support/ErrorHandler.php**:Error handler - **src/Support/Set.php**:Set data structure (O(1) lookup performance using associative array) - **src/Support/ServerConfig.php**:Server config class, single responsibility for configuration - **src/Support/ServerBuilder.php**:Server builder, fluent API simplifies server creation - **src/Support/ServerManager.php**:Server manager, manages lifecycle and adapters ## Architecture Optimization Documentation ### Refactoring Goals The project has been through multiple optimization refactors, achieving: - **High Cohesion**:Each class has clear and single responsibility - **Low Coupling**:Simplified dependency relationships between components - **Low Redundancy**:Eliminated duplicate code - **High Performance**:Multiple performance optimization points - **Easy Maintenance**:Clear code structure, PHPStan 0 errors ### Key Refactoring Tasks 1. **Extracted PacketDispatcher from SocketIOServer**:Specifically handles packet distribution 2. **Extracted AckManager from EventHandler**:Unified management of all ACK callbacks 3. **Merged SocketConn into Socket**:Eliminated redundant wrapper class 4. **Extracted SessionStore and RecoveryManager from Session**:Separated static storage and recovery logic 5. **Extracted SocketEventEmitter Trait from Socket**:Reduced Socket class complexity 6. **Removed double dispatch**:EventHandler no longer needs double routing, directly use PacketDispatcher 7. **Set performance optimization**:Changed from O(n) to O(1) lookup 8. **PacketParser static map**:Performance optimization 9. **Exception class merging**:3 exception classes merged into 1, using static factory methods 10. **Broadcaster chain call optimization**:Use clone instead of direct calls to reduce constructor overhead 11. **EngineIOHandler decoupling**:Use callbacks instead of direct dependencies on EventHandler and RoomManager 12. **fetchSockets simplified**:Use simpler if instead of complex closure 13. **initializeMaps optimization**:Explicitly initialize static maps 14. **Removed ReflectionFunction calls in AckManager**:Reduced unnecessary performance overhead 15. **Adapter cross-process methods added**:Added allSockets, fetchSockets, socketsJoin, socketsLeave, disconnectSockets methods ### Performance Improvements - Set class lookup performance improved from O(n) to O(1) - PacketParser type lookup no longer iterates over enums, now uses static maps - Eliminated redundant object constructor overhead at multiple places - Removed duplicate routing, simplified ACK - Unified ACK callback management, reduced redundancy between Session and AckManager - Adapter supports complete cross-process operations ## Quick Start ### Basic Usage ```php use Workerman\Worker; use PhpSocketIO\SocketIOServer; use Psr\Log\LogLevel; // Create Socket.IO server instance $io = new SocketIOServer('0.0.0.0:8088', [ 'pingInterval' => 25000, // Heartbeat interval (milliseconds) 'pingTimeout' => 20000, // Heartbeat timeout (milliseconds) 'maxPayload' => 10485760, // Maximum payload (bytes) 'workerCount' => 1, // Number of workers, default is 1 'logLevel' => LogLevel::INFO, // Log level ]); // Register connection event handler using $io->of() $io->of('/chat')->on('connection', function ($socket) use ($io) { // Check if this is a recovered connection if ($socket->recovered) { echo "Connection recovered, continuing with previous data!\n"; // $socket->data and room info have been automatically restored // Can resend potentially missed messages } // Send welcome message $socket->emit('welcome', 'Welcome to Socket.IO server!'); // Set custom socket data (saved on disconnect, restored on reconnect) $socket->data['userId'] = 'user_' . time(); $socket->data['name'] = 'Guest'; // Join room (saved on disconnect, automatically restored on reconnect) $socket->join('welcome'); // Chat message handling $socket->on('chat message', function ($msg) use ($socket) { $socket->broadcast->emit('chat message', $msg); }); // ACK message handling - must use callback, do not use return $socket->on('ack', function ($msg, $callback = null) use ($socket) { if (is_callable($callback)) { $callback(['status' => 'ok', 'data' => $msg]); } }); // Disconnect handling $socket->on('disconnect', function () use ($socket) { // Cleanup logic (note: state is automatically saved for recovery on disconnect) }); }); // Start Workerman Worker::runAll(); ``` ### Using ServerBuilder Fluent API ```php use Workerman\Worker; use PhpSocketIO\Support\ServerBuilder; use Psr\Log\LogLevel; // Create server using ServerBuilder fluent API $io = ServerBuilder::create() ->listen('0.0.0.0:8088') ->pingInterval(25000) ->pingTimeout(20000) ->workerCount(1) ->logLevel(LogLevel::INFO) ->cors('*') ->build(); // Subsequent operations are the same as normal $io->of('/chat')->on('connection', function ($socket) { $socket->emit('welcome', 'Welcome!'); }); Worker::runAll(); ``` ### Using Logging ```php use Psr\Log\LogLevel; // 1. Use built-in logger (default) $io = new SocketIOServer('0.0.0.0:8088', [ 'logLevel' => LogLevel::DEBUG ]); // 2. Set custom log handler $io->getLogger()->setHandler(function ($level, $message, $context) { // Can write to file, database, or other log services file_put_contents('/path/to/logs/socketio.log', "[{$level}] {$message}\n", FILE_APPEND ); }); // 3. Use third-party PSR-3 log library, like Monolog $logger = new \Monolog\Logger('socketio'); $logger->pushHandler(new \Monolog\Handler\StreamHandler('/path/to/logs/socketio.log')); $io->setLogger($logger); ``` ### Using Middleware ```php // 1. Global middleware - applies to all namespaces and events $io->use(function ($socket, $packet, $next) { $sid = $socket['id'] ?? 'unknown'; echo "[Global Middleware] SID: {$sid}\n"; $next(); }); // 2. Namespace-level middleware - only applies to /chat namespace $io->of('/chat')->use(function ($socket, $packet, $next) { echo "[Namespace Middleware] /chat\n"; $next(); }); // 3. Socket instance-level middleware - only applies to current connection $io->of('/chat')->on('connection', function ($socket) { $socket->use(function ($packet, $next) use ($socket) { echo "[Socket Middleware] Socket {$socket->id}\n"; $next(); }); }); ``` ### Multi-Worker Configuration Example When using multiple worker processes, you must set an adapter via setAdapter method: #### Using ClusterAdapter (based on Workerman Channel) > Note: Using ClusterAdapter requires installing workerman/channel first: > ```bash > composer require workerman/channel > ``` ```php use Workerman\Worker; use PhpSocketIO\SocketIOServer; use PhpSocketIO\Adapter\ClusterAdapter; // Create multi-worker server instance (4 workers) $io = new SocketIOServer('0.0.0.0:8088', [ 'pingInterval' => 25000, 'pingTimeout' => 20000, 'workerCount' => 4, // Set 4 workers ]); // Create and set cluster adapter $adapter = new ClusterAdapter([ 'channel_ip' => '127.0.0.1', 'channel_port' => 2206, 'prefix' => 'socketio_', 'heartbeat' => 25 ]); $io->setAdapter($adapter); // Event handling code... $io->of('/chat')->on('connection', function ($socket) { // Handle connection... }); Worker::runAll(); ``` #### Using RedisAdapter (based on Redis) > Note: Using RedisAdapter requires installing workerman/redis first: > ```bash > composer require workerman/redis > ``` ```php use Workerman\Worker; use PhpSocketIO\SocketIOServer; use PhpSocketIO\Adapter\RedisAdapter; // Create multi-worker server instance (4 workers) $io = new SocketIOServer('0.0.0.0:8088', [ 'pingInterval' => 25000, 'pingTimeout' => 20000, 'workerCount' => 4, // Set 4 workers ]); // Create and set Redis adapter $adapter = new RedisAdapter([ 'host' => '127.0.0.1', 'port' => 6379, 'auth' => null, // Redis auth password, null if no password 'db' => 0, // Redis database number 'prefix' => 'socketio_', 'heartbeat' => 25 ]); $io->setAdapter($adapter); // Event handling code... $io->of('/chat')->on('connection', function ($socket) { // Handle connection... }); Worker::runAll(); ``` ## Room Operations ```php $io->of('/chat')->on('connection', function ($socket) use ($io) { // Join room $socket->join('room1'); // Leave room $socket->leave('room1'); // Send to specific room only $io->of('/chat')->to('room1')->emit('some event', 'message'); // Send to multiple rooms $io->of('/chat')->to('room1')->to('room2')->emit('some event', 'message'); // Broadcast (excluding current socket) $socket->broadcast->emit('some event', 'message'); // Broadcast within specific room $socket->to('room1')->emit('some event', 'message'); // Exclude specific rooms $socket->except('room2')->emit('some event', 'message'); }); ``` ## Event Acknowledgement (ACK) **Important: ACK responses must use callback, do not use return!** ```php $io->of('/chat')->on('connection', function ($socket) { $socket->on('reqAck', function ($data, $callback = null) { // Process data $result = ['status' => 'ok', 'data' => $data]; // Call callback to send acknowledgement if (is_callable($callback)) { $callback($result); } }); // Server sends ACK message to client $socket->on('ping', function () use ($socket) { $socket->emitWithAck('ackResponse', 'Hello', function ($clientData) { // Handle client response }); }); }); ``` ## Connection Recovery Mechanism This project fully implements the Socket.IO v4 connection state recovery mechanism. When client network is unstable and disconnects, the previous session state can be recovered. ### Features - **Automatic State Saving**: Automatically saves room info, custom data, and sent messages on disconnect - **State Recovery**: Automatically restores rooms and custom data on reconnection - **Lost Message Resend**: Automatically resends potentially lost messages via offset tracking - **Easy Usage**: Check if connection is successfully recovered via `$socket->recovered` property ### Usage Example ```php $io->of('/chat')->on('connection', function ($socket) use ($io) { // Check if connection is recovered if ($socket->recovered) { echo "User connection recovered!\n"; // $socket->data and room info have been automatically restored // Can check if there's data to resume in $socket->data } else { echo "New user connected!\n"; // New connection, initialize data $socket->data['username'] = 'Guest_' . mt_rand(); } // Set custom data (saved on disconnect, restored on reconnect) $socket->data['lastActive'] = time(); // Join room (saved on disconnect, automatically restored on reconnect) $socket->join('chat_room'); // Send message (offset is automatically tracked) $socket->emit('system_message', 'Welcome to the chat room!'); }); ``` ### Client Configuration Client needs to enable reconnection mechanism (Socket.IO client has it enabled by default): ```javascript const io = require('socket.io-client'); // Connect to server (reconnection enabled by default) const socket = io('http://localhost:8088/chat', { // Optional: custom reconnection parameters reconnection: true, reconnectionDelay: 100, reconnectionDelayMax: 500, reconnectionAttempts: 10, }); ``` ### How It Works 1. **Connection Establishment**: Server generates unique `pid` (private id) for each connection 2. **Message Tracking**: Each sent event has `offset` marker 3. **Disconnect Saving**: When connection disconnects, server saves: - All current rooms - Custom data in `$socket->data` - Recently sent event list (with offset) 4. **Reconnection Recovery**: - Client sends previous `pid` and latest `offset` on reconnection - Server validates if pid is valid and not expired - Automatically restores room info and custom data - Resends potentially lost messages after offset - Sets `$socket->recovered = true` 5. **Expiration Cleanup**: Saved state expires after 120 seconds ### Configuration Options Connection recovery mechanism is built into the server, no extra configuration needed. Default parameters: - **Recovery Timeout**: 120 seconds (state cannot be recovered after this time) - **Max Saved Messages**: 1000 (maximum number of events to save) ## Configuration Options | Option | Type | Default | Description | | --- | --- | --- | --- | | `pingInterval` | int | 25000 | Heartbeat interval (milliseconds) | | `pingTimeout` | int | 20000 | Heartbeat timeout (milliseconds) | | `maxPayload` | int | 10485760 | Maximum payload size (bytes) | | `workerCount` | int | 1 | Number of Worker processes | | `logLevel` | string | `LogLevel::INFO` | Log level (PSR-3) | | `ssl` | array | [] | SSL configuration (for HTTPS/WSS) | | `cors` | array/string | null | CORS cross-origin configuration | ### CORS Configuration Supports the following configuration methods: ```php // Method 1: Simple configuration, specify allowed origin only $io = new SocketIOServer('0.0.0.0:8088', [ 'cors' => 'https://example.com' ]); // Method 2: Full configuration $io = new SocketIOServer('0.0.0.0:8088', [ 'cors' => [ 'origin' => 'https://example.com', 'methods' => ['GET', 'POST', 'OPTIONS'], 'allowedHeaders' => ['my-custom-header', 'Content-Type'], 'credentials' => true ] ]); // Method 3: Allow multiple origins (requires dynamic handling) $io = new SocketIOServer('0.0.0.0:8088', [ 'cors' => [ 'origin' => ['https://example.com', 'https://app.example.com'], 'methods' => ['GET', 'POST', 'OPTIONS'], 'allowedHeaders' => ['Content-Type', 'Authorization'], 'credentials' => true ] ]); ``` #### CORS Configuration Options Description | Option | Type | Default | Description | | --- | --- | --- | --- | | `origin` | string/array | `*` | Allowed origins, can be string or array | | `methods` | array | `['GET', 'POST', 'OPTIONS']` | Allowed HTTP methods | | `allowedHeaders` | array | `['Content-Type', 'Authorization']` | Allowed request headers | | `credentials` | bool | `false` | Whether to allow credentials (Cookies) | ## Starting the Server Use the provided server.php to start the server: ```bash # Start server (foreground) php server.php # Start as daemon (background) php server.php -d # Check server status php server.php status # Stop server php server.php stop ``` ## More Information For detailed usage instructions, please refer to [docs/USAGE.md](docs/USAGE.md) file, including: - Complete three-layer middleware system documentation - Correct namespace usage - Detailed ACK mechanism description - API reference documentation - Troubleshooting guide - Performance optimization suggestions - Security considerations ## Version History - **v1.6.0**:Complete architecture optimization refactoring, achieved high cohesion and low coupling, multiple performance optimizations, PHPStan 0 errors - Added SessionStore for specialized session storage management - Added SocketEventEmitter Trait to reduce Socket class complexity - Unified ACK callback management - Optimized Set class lookup performance O(n) → O(1) - PacketParser uses static maps instead of enum iteration - Broadcaster chain calls optimized using clone - Exception classes merged into 1 unified class - EngineIOHandler decoupled using callbacks - Eliminated double dispatch and redundant code - Adapter added cross-process methods: allSockets, fetchSockets, socketsJoin, socketsLeave, disconnectSockets - Numerous performance optimization points - **v1.5.0**:Complete Socket.IO v4 connection state recovery mechanism, added `$socket->recovered` property, supports state recovery, room recovery, and lost message retransmission - **v1.4.0**:PHP 8.1+ optimization, complete three-layer middleware system, fixed ACK mechanism, unified $io->of() usage - **v1.3.0**:Optimized performance and stability, added PSR-3 logging - **v1.2.0**:Added cluster mode support - **v1.1.0**:Added binary data transmission support - **v1.0.0**:Initial version, supports Socket.IO v4 protocol ## Contributing Guide Welcome to submit Issues and Pull Requests to improve this project. Before submitting code, please ensure: 1. Code follows project code style (follows PSR standards) 2. Added appropriate tests 3. Documentation has been updated (README.md, USAGE.md, etc.) 4. All PHP syntax checks pass ## License This project is licensed under the MulanPSL-2.0 License, see [LICENSE](LICENSE) file for details.