How to read wss: / / stream in php without libraries (streaming api vk)

The vk Streaming api allows you to receive events from all over the vk, and this is implemented via the wss: / / protocol. As far as I googled, wss:// is not supported by PHP by default.

Streaming api documentation:

How to implement this without using libraries/recompiling php, etc.?

UPD 1: in fact, wss is ssl over tcp, and in theory the following code should work, but for some reason it outputs a 404 page.

$socket = stream_socket_client("ssl://$endpoint:443/stream?key=$key", $errno, $errstr, 5, STREAM_CLIENT_CONNECT);

        $header = "GET / HTTP/1.1\r\n" .
            "Content-Type:application/json\r\n" .
            "Host: localhost\r\n" .
            "Upgrade: websocket\r\n" .
            "Connection: Upgrade\r\n" .
            "Sec-WebSocket-Version: 13\r\n\r\n";

        fwrite($socket, $header);

        while (!feof($socket)) {
            $context = fgets($socket, 1024);
            print_r($context);
        }

        fclose($socket);
Author: Kirill Minovsky, 2020-01-16

1 answers

It turned out to be done! True, there were many pitfalls.
For those who came here with the same question-read about the implementation of the websocket protocol

  • You really need to knock on ssl:// with port 443.
  • When sending headers after connecting, you need to put the query part of the request in this form

$header = "GET /stream?key={$key} HTTP/1.1\r\n" .
"host: streaming.vk.com:443\r\n" .
"user-agent:websocket-client-php\r\n" .
"connection:Upgrade\r\n" .
"upgrade:websocket\r\n" .
"sec-websocket-key: $key\r\n" .
"sec-websocket-version:13\r\n\r\n";
fwrite($this->socket, $header);

  • The sec-websocket-key header with the generated key must also be present. Read more on the website about the implementation the web socket of the protocol. Here is the implementation of the generator in PHP
function generateKey() {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"$&/()=[]{}0123456789';
        $key = '';
        $chars_length = strlen($chars);
        for ($i = 0; $i < 16; $i++) $key .= $chars[mt_rand(0, $chars_length - 1)];
        return base64_encode($key);
}

And then just goes to calculate the length of the payload, read the payload, catch PING messages from the VC and send PONG.

You can see the full implementation class for working with Streaming in my library, or in the master branch, or in testing along the path src/Streaming.php. There will be an up-to-date version

 0
Author: Kirill Minovsky, 2020-01-30 15:26:57