WebSocket in PHP: Erstellung von Echtzeit-Anwendungen auf fortgeschrittenem Niveau

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

WebSocket in PHP: Von der Theorie zur industriellen Echtzeit-Anwendung



Das WebSocket-Protokoll hat die Webentwicklung revolutioniert, indem es die Erstellung vollwertiger bidirektionaler Kommunikationskanäle zwischen Client und Server ermöglicht. Im Gegensatz zu klassischem AJAX (Long Polling, Server-Sent Events) bietet WebSocket eine dauerhafte Verbindung mit minimalem Overhead. Für PHP-Entwickler ist der Übergang von einfachen „Echo-Server“-Beispielen zu einer industriellen Echtzeit-Anwendung eine ernsthafte Herausforderung, die mit Zustandsverwaltung, Skalierung und asynchroner Verarbeitung verbunden ist.



In diesem Artikel betrachten wir fortgeschrittene Techniken für die Arbeit mit WebSocket in PHP: die Architektur eines Mehrbenutzer-Chats, die Integration mit Redis für horizontale Skalierung, die Verarbeitung von Hintergrundaufgaben und die Leistungsoptimierung.



1. Architektur eines fortgeschrittenen WebSocket-Servers mit Ratchet



Die Bibliothek Ratchet (basierend auf ReactPHP) bleibt der Goldstandard für WebSocket in PHP. Für Produktionslösungen reicht jedoch ein einfaches onMessage nicht aus. Betrachten wir eine komponentenbasierte Architektur mit getrennten Verantwortlichkeiten:



<?phpuse Ratchet\\MessageComponentInterface;use Ratchet\\ConnectionInterface;use React\\EventLoop\\LoopInterface;

class RealTimeHub implements MessageComponentInterface { private $clients; private $loop; private $redis; private $userRegistry;

public function __construct(LoopInterface $loop, \\Redis $redis) { $this->clients = new \\SplObjectStorage; $this->loop = $loop; $this->redis = $redis; $this->userRegistry = []; }

public function onOpen(ConnectionInterface $conn) { $this->clients->attach($conn); echo "Neue Verbindung: {$conn->resourceId}"; }

public function onMessage(ConnectionInterface $from, $msg) { $data = json_decode($msg, true);

switch ($data['type'] ?? '') { case 'auth': $this->handleAuth($from, $data); break; case 'message': $this->handleMessage($from, $data); break; case 'subscribe': $this->handleSubscribe($from, $data); break; default: $from->send(json_encode(['error' => 'Unbekannter Befehl'])); } }

public function onClose(ConnectionInterface $conn) { $this->clients->detach($conn); // Bereinigung der Benutzerregistrierung if (isset($conn->userId)) { unset($this->userRegistry[$conn->userId]); } }

public function onError(ConnectionInterface $conn, \\Exception $e) { $conn->close(); }

private function handleAuth(ConnectionInterface $conn, array $data) { $token = $data['token'] ?? ''; // Überprüfung des JWT-Tokens $userId = $this->validateToken($token); if ($userId) { $conn->userId = $userId; $this->userRegistry[$userId] = $conn; $conn->send(json_encode(['type' => 'auth_ok'])); } else { $conn->send(json_encode(['type' => 'auth_fail'])); } }

private function handleMessage(ConnectionInterface $from, array $data) { $targetUserId = $data['to'] ?? null; if ($targetUserId && isset($this->userRegistry[$targetUserId])) { $this->userRegistry[$targetUserId]->send(json_encode([ 'type' => 'message', 'from' => $from->userId ?? 'anonymous', 'text' => $data['text'] ])); } }

private function validateToken(string $token): ?int { // Simulation der JWT-Überprüfung $payload = json_decode(base64_decode(explode('.', $token)[1] ?? ''), true); return $payl

Blogs

Buchempfehlungen