cboden/Ratchet is a PHP library that allows developers to build real-time, bi-directional communication applications using WebSockets. Unlike traditional HTTP, which is stateless and requires clients to poll the server for updates, WebSockets provide a persistent, full-duplex communication channel between a client and a server. This enables "push" capabilities from the server to the client, leading to more responsive and efficient real-time applications.\n\nWhy Use Ratchet?\n* Real-time Interaction: Facilitates instant updates for chat applications, live dashboards, online gaming, notifications, and more.\n* Reduced Overhead: Eliminates the need for constant HTTP polling, reducing server load and network traffic.\n* Server Push: Allows the server to initiate communication and send data to clients without them explicitly requesting it.\n* PHP Ecosystem: Brings WebSocket server capabilities directly into the PHP environment, leveraging existing PHP skills and tools.\n\nCore Components of Ratchet:\nRatchet integrates with `ReactPHP` for its event-driven, non-blocking I/O model, which is crucial for handling multiple concurrent WebSocket connections efficiently. Key components include:\n* `Ratchet\\MessageComponentInterface`: This is the heart of your application. You implement this interface to define how your application handles different WebSocket events:\n * `onOpen(ConnectionInterface \$conn)`: Called when a new client connects.\n * `onMessage(ConnectionInterface \$from, \$msg)`: Called when a client sends a message.\n * `onClose(ConnectionInterface \$conn)`: Called when a client disconnects.\n * `onError(ConnectionInterface \$conn, \\Exception \$e)`: Called when an error occurs on a connection.\n* `Ratchet\\WebSocket\\WsServer`: Wraps your `MessageComponentInterface` implementation, handling the WebSocket handshake and framing of messages according to the WebSocket protocol.\n* `Ratchet\\Http\\HttpServer`: Handles standard HTTP requests (e.g., the initial WebSocket handshake).\n* `Ratchet\\Server\\IoServer`: The main server component that binds everything together. It listens for incoming connections on a specific port and passes them to the appropriate handlers (HTTP or WebSocket). It requires an `EventLoop` (provided by `ReactPHP`) to manage asynchronous operations.\n* `React\\EventLoop\\LoopInterface`: The asynchronous event loop that powers Ratchet, allowing it to handle many connections concurrently without blocking.\n\nHow Ratchet Works:\n1. Client Connection: A client (e.g., a web browser using JavaScript's `WebSocket` API) attempts to connect to the Ratchet server via a `ws://` or `wss://` URL.\n2. HTTP Handshake: The initial connection is an HTTP request. `Ratchet\\Http\\HttpServer` handles this.\n3. WebSocket Upgrade: If the HTTP request includes the correct `Upgrade: websocket` header, `Ratchet\\WebSocket\\WsServer` performs the WebSocket handshake, upgrading the connection from HTTP to WebSocket.\n4. Persistent Connection: Once upgraded, a persistent, bi-directional connection is established.\n5. Event Handling: Your application, implementing `MessageComponentInterface`, receives events (`onOpen`, `onMessage`, `onClose`, `onError`) for each connection.\n6. Real-time Communication: Messages can now be sent back and forth between the server and any connected client over this persistent channel.\n\nInstallation (via Composer):\nTo use Ratchet, you typically install it via Composer:\n`composer require cboden/ratchet react/socket react/http`\n\nExample Use Case:\nA simple chat application where multiple clients can connect and send messages to each other in real-time.
Example Code
<?php\nuse Ratchet\\MessageComponentInterface;\nuse Ratchet\\ConnectionInterface;\nuse Ratchet\\Server\\IoServer;\nuse Ratchet\\Http\\HttpServer;\nuse Ratchet\\WebSocket\\WsServer;\nuse React\\EventLoop\\Loop;\n\nrequire __DIR__ . '/vendor/autoload.php';\n\n// Our chat application component\nclass Chat implements MessageComponentInterface {\n protected \$clients;\n\n public function __construct() {\n \$this->clients = new \\SplObjectStorage; // Store all connected clients\n }\n\n public function onOpen(ConnectionInterface \$conn) {\n // Store the new connection to send messages to later\n \$this->clients->attach(\$conn);\n echo "New connection! ({\$conn->resourceId})\n";\n }\n\n public function onMessage(ConnectionInterface \$from, \$msg) {\n \$numRecv = count(\$this->clients) - 1;\n echo sprintf('Connection %d sending message \"%s\" to %d other connection(s)' . "\n"\n , \$from->resourceId, \$msg, \$numRecv);\n\n foreach (\$this->clients as \$client) {\n if (\$from !== \$client) {\n // The sender is not the receiver, so send to others\n \$client->send(\$msg);\n }\n }\n }\n\n public function onClose(ConnectionInterface \$conn) {\n // Detach the connection when it's closed\n \$this->clients->detach(\$conn);\n echo "Connection {\$conn->resourceId} has disconnected\n";\n }\n\n public function onError(ConnectionInterface \$conn, \\Exception \$e) {\n echo "An error has occurred: {\$e->getMessage()}\n";\n \$conn->close();\n }\n}\n\n// Set up the Ratchet server\n\$loop = Loop::get(); // Get the default event loop\n\n\$server = IoServer::factory(\n new HttpServer(\n new WsServer(\n new Chat()\n )\n ),\n 8080, // Port to listen on\n '0.0.0.0', // Listen on all available network interfaces\n \$loop // Pass the event loop\n);\n\necho "Ratchet server started on port 8080\n";\n\$server->run();\n\n/*\nTo run this example:\n1. Make sure you have Composer installed.\n2. Create a directory (e.g., 'ratchet_chat').\n3. Create `composer.json` inside it:\n ```json\n {\n \"require\": {\n \"cboden/ratchet\": \"^0.4\",\n \"react/socket\": \"^1.0\",\n \"react/http\": \"^1.0\"\n },\n \"autoload\": {\n \"psr-4\": {\n \"App\\\": \"src/\"\n }\n }\n }\n ```\n4. Run `composer install`.\n5. Save the PHP code above as `server.php` in the root of your project.\n6. Open your terminal and run `php server.php`.\n\nClient-side HTML/JavaScript (save as `index.html` in the same directory and open in browser):\n```html\n<!DOCTYPE html>\n<html>\n<head>\n <title>Ratchet Chat Client</title>\n <style>\n body { font-family: sans-serif; }\n #messages { border: 1px solid #ccc; padding: 10px; height: 300px; overflow-y: scroll; margin-bottom: 10px; }\n .message { margin-bottom: 5px; }\n </style>\n</head>\n<body>\n <h1>Ratchet Chat Client</h1>\n <div id=\"messages\"></div>\n <input type=\"text\" id=\"messageInput\" placeholder=\"Type your message...\" style=\"width: 80%;\">\n <button id=\"sendButton\">Send</button>\n\n <script>\n const conn = new WebSocket('ws://localhost:8080');\n const messagesDiv = document.getElementById('messages');\n const messageInput = document.getElementById('messageInput');\n const sendButton = document.getElementById('sendButton');\n\n function appendMessage(msg, type = 'received') {\n const p = document.createElement('p');\n p.className = 'message ' + type;\n p.textContent = msg;\n messagesDiv.appendChild(p);\n messagesDiv.scrollTop = messagesDiv.scrollHeight; // Scroll to bottom\n }\n\n conn.onopen = function(e) {\n console.log(\"Connection established!\");\n appendMessage(\"Connected to chat server.\", 'system');\n };\n\n conn.onmessage = function(e) {\n console.log(e.data);\n appendMessage(\"Other: \" + e.data, 'received');\n };\n\n conn.onclose = function(e) {\n console.log(\"Connection closed.\");\n appendMessage(\"Disconnected from chat server.\", 'system');\n };\n\n conn.onerror = function(e) {\n console.error(\"WebSocket Error: \", e);\n appendMessage(\"Connection error: \" + e.message, 'error');\n };\n\n sendButton.onclick = function() {\n const message = messageInput.value;\n if (message) {\n conn.send(message);\n appendMessage(\"You: \" + message, 'sent');\n messageInput.value = ''; // Clear input\n }\n };\n\n messageInput.addEventListener('keypress', function(e) {\n if (e.key === 'Enter') {\n sendButton.click();\n }\n });\n </script>\n</body>\n</html>\n```\n*/








cboden/Ratchet