Build Real-Time WebSocket Server with Ratchet in PHP – Step-by-Step Guide
This guide explains how to use the Ratchet PHP library to create an asynchronous WebSocket server, covering WebSocket fundamentals, the handshake protocol, required HTTP headers, Composer installation, full server‑side code, a simple HTML/JavaScript client, and visual demo screenshots.
Overview
Ratchet is a PHP library for building asynchronous WebSocket services. It lets you create applications with a simple interface and compose reusable components without modifying core code.
What is WebSocket?
WebSocket is a full‑duplex communication protocol that runs over a single TCP connection, allowing the server to push data to the client after an initial handshake.
Handshake Process
The client sends an HTTP GET request with specific headers (Connection, Upgrade, Sec‑WebSocket‑Key, Origin, Sec‑WebSocket‑Protocol, Sec‑WebSocket‑Version). The server replies with a 101 Switching Protocols response containing Upgrade, Connection, Sec‑WebSocket‑Accept and optionally Sec‑WebSocket‑Protocol.
Header field details
Connectionmust be set to Upgrade to indicate a protocol upgrade request. Upgrade must be websocket to request the WebSocket protocol. Sec‑WebSocket‑Key is a random base64 string; the server appends the GUID 258EAFA5‑E914‑47DA‑95CA‑C5AB0DC85B11, hashes it with SHA‑1, then base64‑encodes the result to produce Sec‑WebSocket‑Accept. Sec‑WebSocket‑Version must be 13 as defined by RFC 6455. Origin is optional and indicates the page that initiated the connection; it differs from the HTTP Referer header.
Server implementation
First create a project directory and install Ratchet and its dependencies with Composer:
mkdir ratchet.websocket.tinywan.cn
composer require cboden/ratchetThe main server class implements MessageComponentInterface and defines onOpen, onMessage, onClose and onError methods. A minimal example is shown below:
<?php
require __DIR__ . '/vendor/autoload.php';
use Ratchet\ConnectionInterface;
use Ratchet\WebSocket\MessageComponentInterface;
class WebsocketServer implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn) {
$this->clients->attach($conn);
echo "New connection! ({$conn->resourceId})
";
}
public function onMessage(ConnectionInterface $from, $msg) {
$numRecv = count($this->clients) - 1;
echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "
",
$from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
foreach ($this->clients as $client) {
$client->send($msg);
}
}
public function onClose(ConnectionInterface $conn) {
$this->clients->detach($conn);
echo "Connection {$conn->resourceId} has disconnected
";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "An error has occurred: {$e->getMessage()}
";
$conn->close();
}
}
$server = \Ratchet\Server\IoServer::factory(
new \Ratchet\Http\HttpServer(
new \Ratchet\WebSocket\WsServer(new WebsocketServer())
),
8585
);
$server->run();Run the server with:
php WebsocketServer.phpClient example
A simple HTML page using native JavaScript WebSocket connects to ws://127.0.0.1:8585 and displays messages:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Real-time WebSocket</title>
<script src="http://cdn.bootcss.com/jquery/2.1.3/jquery.min.js"></script>
</head>
<body>
<h2>WebSocket Demo</h2>
<input id="data" type="text" style="height:50px;width:100%;">
<button id="submit" onclick="sub()" style="height:50px;width:100%;">Submit</button>
<div id="output"></div>
<script type="text/javascript">
var wsUri = "ws://127.0.0.1:8585";
var websocket, output;
function init() {
output = document.getElementById("output");
websocket = new WebSocket(wsUri);
websocket.onopen = function () { writeToScreen("CONNECTED"); };
websocket.onclose = function () { writeToScreen("DISCONNECTED"); };
websocket.onmessage = function (evt) { writeToScreen('<span style="color:blue">RESPONSE: </span>' + evt.data); };
websocket.onerror = function (evt) { writeToScreen('<span style="color:red">ERROR:</span> ' + evt.data); };
}
function writeToScreen(message) {
var p = document.createElement("p");
p.style.wordWrap = "break-word";
p.innerHTML = message;
output.appendChild(p);
}
function sub() {
websocket.send($("#data").val());
}
window.addEventListener("load", init, false);
</script>
</body>
</html>Demo screenshots
Server console output:
Client browser view:
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Tech Hub
Sharing cutting-edge internet technologies and practical AI resources.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
