Menu

Reference / Http\WebSocket

connect()

function
function connect(
    string $url,
    ?Options $o = null,
    array<string,string> $headers = []
): Connection

Open a WebSocket client connection to a ws:// or wss:// URL.

wss:// uses TLS with SNI and certificate verification; configure it through Options::$sslContext. The default port is 80 for ws:// and 443 for wss://. The client checks the server's answer itself: the status must be 101, Sec-WebSocket-Accept must match, and a subprotocol or extension in the answer must be one that was offered. Redirects are not followed. Options::$connectTimeout bounds the TCP/TLS connect and the handshake response together, as one deadline.

Outside Async\async() the call blocks the process on ordinary sockets; inside it, it suspends only the calling fiber, so many connections can run concurrently.

$ws = Http\WebSocket\connect('wss://example.com/feed');
$ws->send('hello');
foreach ($ws as $m) {
    echo $m->data, "\n";
}

Parameters

$url string
ws://host[:port]/path?query or wss://...
$o Options|null = null
settings; defaults when null
$headers array<string,string> = []
extra request headers (Origin, Authorization, …)

Returns

Connection — the open connection

Throws

HandshakeException
for any other scheme, an empty host, CR/LF/NUL in the URL, a failed connect, a timeout, or a handshake the server refused or answered incorrectly
\ValueError
when a header name or value is empty-named, contains CR, LF or NUL, or names Host, Upgrade, Connection or a Sec-WebSocket-* header

Example

// An echo server and a client in one program, over loopback.

use function Async\async;
use function Async\spawn;
use Http\WebSocket as WS;

$l = stream_socket_server('tcp://127.0.0.1:0');
stream_set_blocking($l, false);
$name = stream_socket_get_name($l, false);
$port = (int)substr($name, strrpos($name, ':') + 1);
$server = \Http\Server::onListener($l)->acceptWait(0.02);

async(function () use ($server, $port) {
    spawn(function () use ($server) {
        $server->serve(function (\Http\Request $req): \Http\Response {
            return WS\upgrade($req, function (WS\Connection $ws): void {
                foreach ($ws as $m) {
                    if ($m->binary) {
                        $ws->sendBinary($m->data);
                    } else {
                        $ws->send('echo: ' . $m->data);
                    }
                }
            });
        });
    });

    $ws = WS\connect("ws://127.0.0.1:$port/");
    $ws->send('hello');
    $m = $ws->receive();
    echo $m->data, ' (', $m->binary ? 'binary' : 'text', ")\n";

    $ws->sendBinary("\x00\x01\x02");
    $m = $ws->receive();
    echo bin2hex($m->data), ' (', $m->binary ? 'binary' : 'text', ")\n";

    $ws->close(1000, 'done');
    echo 'open: ', var_export($ws->isOpen(), true), ', close code: ', $ws->closeCode(), "\n";
    $server->stop();
});

Output

echo: hello (text)
000102 (binary)
open: false, close code: 1000

See also: upgrade

View source