Клиент WebSocket в PHP?

Есть ли библиотека или клиент для подключения к серверу WebSocket с PHP? Если нет, есть ли причина?

phpwebsocket только есть код клиента Javascript.)

Ни один из вышеперечисленных вопросов не является хорошим ответом. Некоторые из них относятся к серверу, тогда как вопрос касается клиента. Код от Rodislav не работал для меня, так как он не разговаривал с моим сервером WebSockets на Heroku. Однако эта библиотека работала очень хорошо:

https://github.com/Devristo/phpws

ОБНОВЛЕНИЕ: Несмотря на то, что этот код работал, когда все было хорошо, кажется, что ошибок или исключений вообще нет, и в результате он непригоден, когда есть ошибка (например, сервер не работает, адрес неверен, порт заблокирован и т. д.). Таким образом, пока было интересно экспериментировать, он не может использоваться в производственном коде.

хорошо, это легко, и вы можете сделать это. Спасибо всем источникам, где мы нашли ответы (извините, я не помню всех)

<?php $host = '10.9.8.173'; //where is the websocket server $port = 8575; $local = "http://mypc"; //url where this script run $data = "first message"; //data to be send $head = "GET / HTTP/1.1"."\r\n". "Upgrade: WebSocket"."\r\n". "Connection: Upgrade"."\r\n". "Origin: $local"."\r\n". "Host: $host"."\r\n". "Sec-WebSocket-Key: asdasdaas76da7sd6asd6as7d"."\r\n". "Content-Length: ".strlen($data)."\r\n"."\r\n"; //WebSocket handshake $sock = fsockopen($host, $port, $errno, $errstr, 2); fwrite($sock, $head ) or die('error:'.$errno.':'.$errstr); $headers = fread($sock, 2000); echo $headers; fwrite($sock, hybi10Encode($data)) or die('error:'.$errno.':'.$errstr); $wsdata = fread($sock, 2000); var_dump(hybi10Decode($wsdata)); fclose($sock); function hybi10Decode($data) { $bytes = $data; $dataLength = ''; $mask = ''; $coded_data = ''; $decodedData = ''; $secondByte = sprintf('%08b', ord($bytes[1])); $masked = ($secondByte[0] == '1') ? true : false; $dataLength = ($masked === true) ? ord($bytes[1]) & 127 : ord($bytes[1]); if($masked === true) { if($dataLength === 126) { $mask = substr($bytes, 4, 4); $coded_data = substr($bytes, 8); } elseif($dataLength === 127) { $mask = substr($bytes, 10, 4); $coded_data = substr($bytes, 14); } else { $mask = substr($bytes, 2, 4); $coded_data = substr($bytes, 6); } for($i = 0; $i < strlen($coded_data); $i++) { $decodedData .= $coded_data[$i] ^ $mask[$i % 4]; } } else { if($dataLength === 126) { $decodedData = substr($bytes, 4); } elseif($dataLength === 127) { $decodedData = substr($bytes, 10); } else { $decodedData = substr($bytes, 2); } } return $decodedData; } function hybi10Encode($payload, $type = 'text', $masked = true) { $frameHead = array(); $frame = ''; $payloadLength = strlen($payload); switch ($type) { case 'text': // first byte indicates FIN, Text-Frame (10000001): $frameHead[0] = 129; break; case 'close': // first byte indicates FIN, Close Frame(10001000): $frameHead[0] = 136; break; case 'ping': // first byte indicates FIN, Ping frame (10001001): $frameHead[0] = 137; break; case 'pong': // first byte indicates FIN, Pong frame (10001010): $frameHead[0] = 138; break; } // set mask and payload length (using 1, 3 or 9 bytes) if ($payloadLength > 65535) { $payloadLengthBin = str_split(sprintf('%064b', $payloadLength), 8); $frameHead[1] = ($masked === true) ? 255 : 127; for ($i = 0; $i < 8; $i++) { $frameHead[$i + 2] = bindec($payloadLengthBin[$i]); } // most significant bit MUST be 0 (close connection if frame too big) if ($frameHead[2] > 127) { $this->close(1004); return false; } } elseif ($payloadLength > 125) { $payloadLengthBin = str_split(sprintf('%016b', $payloadLength), 8); $frameHead[1] = ($masked === true) ? 254 : 126; $frameHead[2] = bindec($payloadLengthBin[0]); $frameHead[3] = bindec($payloadLengthBin[1]); } else { $frameHead[1] = ($masked === true) ? $payloadLength + 128 : $payloadLength; } // convert frame-head to string: foreach (array_keys($frameHead) as $i) { $frameHead[$i] = chr($frameHead[$i]); } if ($masked === true) { // generate a random mask: $mask = array(); for ($i = 0; $i < 4; $i++) { $mask[$i] = chr(rand(0, 255)); } $frameHead = array_merge($frameHead, $mask); } $frame = implode('', $frameHead); // append payload to frame: for ($i = 0; $i < $payloadLength; $i++) { $frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i]; } return $frame; } ?> 

Библиотека PHP Websocket с примером приложения чата. С демо и полное описание реализации.

http://www.techzonemind.com/php-websocket-library-two-way-real-time-communication/

Эта библиотека выглядит неплохо, если вы в порядке с зависимостями: https://github.com/gabrielbull/php-websocket-client

Я попытался использовать многие из вышеперечисленных, чтобы включить в tivoka (json-rpc), но они либо не были достаточно хороши, читая большие пакеты (не получая весь кадр, ни чтение в следующий), либо имели большие зависимости.

Итак, я написал https://github.com/Textalk/websocket-php

Вместо того, чтобы сначала считывать все доступные данные из сокета и затем декодировать его, он считывает заголовок фрейма и анализирует длину полезной нагрузки, а затем загружает именно это.

Ему не хватает поддержки ping / pong, но я думаю, что он отлично справляется с большинством других вещей. Он хорошо работает с tivoka и, по крайней мере, на 92% автозапущен 🙂 Для проверки наличия другого фрейма, возможно, потребуется несколько дополнительных функций.

Дайте мне знать, что вы думаете.