textalk/websocket-php

repository·master·Indexed 21 days ago

https://github.com/textalk/websocket-php

A PHP library providing a WebSocket client and a basic single-threaded server. It handles low-level protocol requirements such as handshakes and ping/pong operations. The library supports PHP versions from 5.4 up to 8.0, depending on the version used. It includes the WebSocket\Client for reading and writing to streams and a rudimentary WebSocket\Server for single-stream implementations.

Tokens
7.8K
Snippets
33
Records
43
Agent score
74%

What's inside textalk-websocket-php

  1. Enable Message objects instead of strings

    master

    By default, the receive() method on a WebSocket\Client or WebSocket\Server returns a string. To receive structured WebSocket\Message\Message instances instead, you must set the return_obj option to true during instantiation.

    When enabled, the returned object will be an instance of a specific class corresponding to the WebSocket opcode:

    • WebSocket\Message\Text
    • WebSocket\Message\Binary
    • WebSocket\Message\Ping
    • WebSocket\Message\Pong
    • WebSocket\Message\Close
    $client = new WebSocket\Client('ws://example.com/', ['return_obj' => true]);
    $message = $client->receive(); // Returns a Message object
  2. How the WebSocket Server works

    master

    The WebSocket\Server is a rudimentary single-stream, single-threaded server. It handles the WebSocket Upgrade handshake, implicit close operations, and ping/pong operations automatically.

    Important Limitations:

    • It does not support threading.
    • It does not support automatic association of continuous client requests.

    If you require multi-threaded behavior or complex client management, you must build a custom implementation on top of this server.

  3. Filter received message types

    master

    By default, receive() only returns messages with text or binary opcodes. You can change this behavior by passing a filter array in the constructor options. Supported opcodes include text, binary, ping, pong, and close.

    // Only return 'text' messages
    $server = new WebSocket\Server(['filter' => ['text']]);
    $server->receive();
    
    // Return all message types
    $server = new WebSocket\Server(['filter' => ['text', 'binary', 'ping', 'pong', 'close']]);
    $server->receive();
  4. Use EchoLogger for synchronous debugging

    master

    In development environments where dev dependencies are installed via Composer, you can use EchoLogger to print library information synchronously to the console. This is useful for debugging client and server interactions. For production environments, you should replace this with a proper logging implementation.

    namespace WebSocket;
    
    $logger = new EchoLogger();
    
    $client = new Client('ws://echo.websocket.org/');
    $client->setLogger($logger);
    
    $server = new Server();
    $server->setLogger($logger);
  5. Listen to a server continuously

    master

    To continuously listen for incoming messages, wrap the receive() call in a loop. Because the client throws exceptions on any failure (including recoverable ones like timeouts), you should wrap the operation in a try-catch block. Catching WebSocket\ConnectionException allows you to handle errors and attempt a reconnection in the next loop iteration.

    $client = new WebSocket\Client("ws://echo.websocket.org/");
    while (true) {
        try {
            $message = $client->receive();
            // Act on received message
            // Break while loop to stop listening
        } catch (\WebSocket\ConnectionException $e) {
            // Possibly log errors
        }
    }
    $client->close();
  6. Listen continuously to incoming clients

    master

    To create a persistent server that listens for multiple clients, wrap the accept() method in a while loop.

    Error Handling: The server methods throw exceptions on any failure, including recoverable ones like connection timeouts. You must wrap the receive() call in a try...catch block for WebSocket\ConnectionException. Consuming these exceptions allows the loop to continue and attempt to re-connect or accept the next client in the next iteration.

    $server = new WebSocket\Server();
    while ($server->accept()) {
        try {
            $message = $server->receive();
            // Act on received message
            // Break while loop to stop listening
        } catch (\WebSocket\ConnectionException $e) {
            // Possibly log errors
        }
    }
    $server->close();
  7. Install textalk/websocket via Composer

    master

    The preferred way to install this library is using Composer.

    PHP Version Compatibility:

    • PHP ^7.4 or ^8.0: Use the latest version.
    • PHP 7.2 or 7.3: Use version 1.5.
    • PHP 7.1: Use version 1.4.
    • PHP ^5.4 or 7.0: Use version 1.3.
    composer require textalk/websocket
  8. Configure WebSocket\Server options

    master

    The WebSocket\Server constructor accepts an associative array of configuration options:

    OptionTypeDefaultDescription
    filterarray['text', 'binary']Array of opcodes to return on receive()
    fragment_sizeint4096Maximum payload size in characters
    loggerPsr\Log\LoggerInterfacenullA PSR-3 compatible logger
    portint8000The server port to listen to
    return_objboolfalseIf true, receive() returns a Message instance instead of a string
    timeoutint5Time out in seconds
    $server = new WebSocket\Server([
        'filter' => ['text', 'binary', 'ping'],
        'logger' => $my_psr3_logger,
        'port' => 9000,
        'return_obj' => true,
        'timeout' => 60,
    ]);
  9. Configure WebSocket\Client options

    master

    The WebSocket\Client constructor accepts an associative array of options to customize connection behavior:

    OptionDescription
    contextA stream context created via stream_context_create()
    filterArray of opcodes to return on receive(). Default: ['text', 'binary']
    fragment_sizeMaximum payload size in characters. Default: 4096
    headersAssociative array of additional headers (e.g., Sec-WebSocket-Protocol)
    loggerA PSR-3 compatible logger
    persistentIf true, the connection is re-used until timeout. Default: false
    return_objIf true, receive() returns a WebSocket\Message instance instead of a string. Default: false
    timeoutConnection/socket timeout in seconds. Default: 5
    $context = stream_context_create();
    stream_context_set_option($context, 'ssl', 'verify_peer', false);
    stream_context_set_option($context, 'ssl', 'verify_peer_name', false);
    
    $client = new WebSocket\Client("ws://echo.websocket.org/", [
        'context' => $context,
        'filter' => ['text', 'binary', 'ping'],
        'headers' => [
            'Sec-WebSocket-Protocol' => 'soap',
            'origin' => 'localhost',
        ],
        'logger' => $my_psr3_logger,
        'return_obj' => true,
        'timeout' => 60,
    ]);
  10. Handle incoming WebSocket connections

    master

    To start accepting connections, call accept(). Note that this implementation is blocking; calling accept() will disconnect existing connections and focus on the new incoming request.

    Once a connection is established, you can use receive() to read messages. receive() is also a blocking operation that reads from the first available connection. It will return:

    • The message content (string) if return_obj is false.
    • A Message instance if return_obj is true.
    • null if a close opcode is received or if the connection is lost.

    You can check the type of the last received message using getLastOpcode().

    $server = new Server(['port' => 8000]);
    $server->accept();
    
    while ($message = $server->receive()) {
        echo "Received: " . $message . "\n";
        $server->send("Echo: " . $message);
    }
  11. Initialize the WebSocket Server

    master

    Create a new instance of WebSocket\Server by passing an associative array of options. The server will attempt to bind to a port (defaulting to 8000) and will automatically increment the port number if the requested one is already in use, up to port 10000.

    Available configuration options:

    • filter: Array of opcodes to handle (e.g., ['text', 'binary']). Default: ['text', 'binary'].
    • fragment_size: Size of message fragments in bytes. Default: 4096.
    • logger: A PSR-3 compatible logger. Default: NullLogger.
    • port: The port to listen on. Default: 8000.
    • return_obj: If true, the receive() method returns a Message instance instead of the raw content. Default: false.
    • timeout: Socket timeout in seconds. Default: null (blocks indefinitely).
    use WebSocket\Server;
    
    $server = new Server([
        'port' => 8080,
        'return_obj' => true,
        'filter' => ['text']
    ]);
  12. Initialize the WebSocket Client

    master

    To connect to a WebSocket server, instantiate the WebSocket\Client class with a ws:// or wss:// URI. You can optionally pass an associative array of configuration options.

    Available Options:

    • context: A valid PHP stream context.
    • timeout: Socket timeout in seconds (default: 5).
    • fragment_size: Size of message fragments in bytes (default: 4096).
    • headers: An associative array of HTTP headers to include in the handshake.
    • logger: A PSR-3 compatible logger instance.
    • persistent: Boolean indicating if the connection should be persistent (default: false).
    • return_obj: Boolean; if true, receive() returns the message object instead of the content (default: false).
    use WebSocket\Client;
    
    $client = new Client('ws://echo.websocket.org', [
        'timeout' => 10,
        'headers' => [
            'Authorization' => 'Bearer my-token',
        ],
    ]);