Devesh Kumar No comments

Php websocket implementation with example



While providing a single "best" example is difficult as it depends on your specific needs and complexity, here are a few approaches and examples for creating PHP WebSocket applications:

1. Using a Library (Recommended for most cases):

Libraries abstract away the low-level details of the WebSocket protocol, making development much easier. Popular choices include:

  • Ratchet: A widely used, event-driven WebSocket library for PHP.

    • Installation: composer require cboden/ratchet

    • Basic Server Example (from Video SDK):

      PHP
      <?php
      use Ratchet\Server\IoServer;
      use Ratchet\Http\HttpServer;
      use Ratchet\WebSocket\WsServer;
      use Ratchet\MessageComponentInterface;
      use Ratchet\ConnectionInterface;
      
      require __DIR__ . '/vendor/autoload.php';
      
      class Chat 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})\n";
          }
      
          public function onMessage(ConnectionInterface $from, $msg) {
              echo sprintf('Connection %d sending message "%s" to %d other connection(s)' . "\n"
                  , $from->resourceId, $msg, count($this->clients) - 1);
      
              foreach ($this->clients as $client) {
                  if ($from !== $client) {
                      $client->send($msg);
                  }
              }
          }
      
          public function onClose(ConnectionInterface $conn) {
              $this->clients->detach($conn);
              echo "Connection {$conn->resourceId} has disconnected\n";
          }
      
          public function onError(ConnectionInterface $conn, \Exception $e) {
              echo "An error has occurred: {$e->getMessage()}\n";
              $conn->close();
          }
      }
      
      $server = IoServer::factory(
          new HttpServer(
              new WsServer(
                  new Chat()
              )
          ),
          8080
      );
      
      $server->run();
      ?>
      
    • Basic JavaScript Client:

      JavaScript
      const socket = new WebSocket('ws://localhost:8080');
      
      socket.onopen = function(event) {
          console.log('Connected to WebSocket server.');
      };
      
      socket.onmessage = function(event) {
          console.log('Message from server: ', event.data);
      };
      
      socket.onclose = function(event) {
          console.log('Disconnected from WebSocket server.');
      };
      
      socket.onerror = function(error) {
          console.error('WebSocket error: ', error);
      };
      
      // Send a message to the server
      socket.send('Hello Server!');
      
  • Bloatless PHP WebSocket: A simpler, more lightweight WebSocket server implementation.

    • Installation: composer require bloatless/websocket
    • Refer to the GitHub repository for usage examples of the server, applications, and client-side JavaScript.
  • Textalk/websocket-php: Provides both a WebSocket client and a rudimentary server.

    • Installation: composer require textalk/websocket
    • See the GitHub repository for client and server examples. Note that the server is single-threaded.
  • OpenSwoole (or Swoole): A powerful asynchronous and concurrent networking framework for PHP, including WebSocket support.

    • Installation: Requires installing the Swoole PHP extension (usually via PECL).
    • Refer to the DEV Community article for a comprehensive example using OpenSwoole.

2. Building from Scratch (More complex, for deeper understanding):

You can implement WebSockets in PHP using the built-in sockets extension. This requires a more thorough understanding of the WebSocket handshake and frame structure.

  • Basic Server Example (from PieHost):

    PHP
    <?php
    $host = '127.0.0.1';
    $port = 8080;
    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
    socket_bind($socket, $host, $port);
    socket_listen($socket);
    echo "WebSocket server started on $host:$port\n";
    $clients = [];
    while (true) {
        $changedSockets = $clients;
        $changedSockets[] = $socket;
        $write = [];
        $except = [];
        socket_select($changedSockets, $write, $except, 0, 10);
        if (in_array($socket, $changedSockets)) {
            $newSocket = socket_accept($socket);
            $clients[] = $newSocket;
            $header = socket_read($newSocket, 1024);
            performHandshake($header, $newSocket, $host, $port);
            socket_getpeername($newSocket, $ip, $remotePort);
            echo "New client connected: $ip:$remotePort\n";
            $foundSocket = array_search($socket, $changedSockets);
            unset($changedSockets[$foundSocket]);
        }
        foreach ($changedSockets as $clientSocket) {
            $data = @socket_recv($clientSocket, $buffer, 1024, 0);
            if ($data === false || $data === 0) {
                // Client disconnected
                echo "Client disconnected\n";
                $clientKey = array_search($clientSocket, $clients);
                unset($clients[$clientKey]);
                socket_close($clientSocket);
                continue;
            }
            // Process incoming message and broadcast to other clients (implementation needed)
            $unmaskedData = unmask($buffer);
            echo "Received: " . $unmaskedData . "\n";
            foreach ($clients as $recipient) {
                if ($recipient !== $clientSocket) {
                    sendMessage($recipient, $unmaskedData);
                }
            }
        }
    }
    socket_close($socket);
    
    // ... (Implement performHandshake, unmask, mask, sendMessage functions as shown in the PieHost article) ...
    ?>
    
    • Basic HTML/JavaScript Client (from PieHost):

      HTML
      <!DOCTYPE html>
      <html>
      <head>
          <title>WebSocket Client</title>
      </head>
      <body>
          <h2>WebSocket Test</h2>
          <div id="output"></div>
          <input type="text" id="message" placeholder="Enter message">
          <button onclick="sendMessage()">Send</button>
      
          <script>
              let socket;
              function connect() {
                  socket = new WebSocket("ws://127.0.0.1:8080");
                  socket.onopen = function(event) {
                      document.getElementById("output").innerHTML += "<span style='color: green;'>Connected to server</span><br>";
                  };
                  socket.onmessage = function(event) {
                      document.getElementById("output").innerHTML += "<span>Message received: " + event.data + "</span><br>";
                  };
                  socket.onclose = function(event) {
                      document.getElementById("output").innerHTML += "<span style='color: red;'>Disconnected from server</span><br>";
                  };
                  socket.onerror = function(error) {
                      document.getElementById("output").innerHTML += "<span style='color: red;'>Error: " + error + "</span><br>";
                  };
              }
              function sendMessage() {
                  if (socket && socket.readyState === WebSocket.OPEN) {
                      const message = document.getElementById("message").value;
                      socket.send(message);
                      document.getElementById("output").innerHTML += "<span>Message sent: " + message + "</span><br>";
                      document.getElementById("message").value = "";
                  } else {
                      document.getElementById("output").innerHTML += "<span style='color: orange;'>Not connected to server</span><br>";
                  }
              }
              connect();
          </script>
      </body>
      </html>
      

Choosing the Right Approach:

  • For most real-world applications, using a library like Ratchet or Bloatless is highly recommended due to ease of use, handling of WebSocket intricacies, and often better performance and features.
  • If you need high-performance, asynchronous operations and are comfortable with extensions, OpenSwoole is a powerful option.
  • Building from scratch is generally for educational purposes or very specific low-level control, as it requires significant effort to implement the WebSocket protocol correctly and handle potential issues.

Remember to install the necessary libraries using Composer if you choose a library-based approach. You'll typically run the PHP WebSocket server script from your command line.


Comments (0)

Post a Comment

Cancel