Connecting to websocket with a PHP client

I am trying to connect a PHP client to a websocket server.

Here is the code I used, which has been widely published in various forums. But for some reason, I just can't get it to work.

Any help would be appreciated.

$host = 'host'; //where is the websocket server $port = 443; //ssl $local = "http://www.example.com/"; //url where this script run $data = '{"id": 2,"command": "server_info"}'; //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". "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); fwrite($sock, "\x00$data\xff" ) or die('error:'.$errno.':'.$errstr); $wsdata = fread($sock, 2000); //receives the data included in the websocket package "\x00DATA\xff" $retdata = trim($wsdata,"\x00\xff"); //extracts data ////WebSocket handshake fclose($sock); echo $retdata; 
+11
source share
3 answers

I would prefer to use the existing websocket client library (maybe https://github.com/gabrielbull/php-websocket-client or https://github.com/Devristo/phpws/tree/master/src/Devristo/Phpws/Client ? ), not a roll, but I got it, at least with:

 $head = "GET / HTTP/1.1"."\r\n". "Host: $host"."\r\n". "Upgrade: websocket"."\r\n". "Connection: Upgrade"."\r\n". "Sec-WebSocket-Key: asdasdaas76da7sd6asd6as7d"."\r\n". "Sec-WebSocket-Version: 13"."\r\n". "Content-Length: ".strlen($data)."\r\n"."\r\n"; 

My server uses TLS / SSL, so I also need to:

 $sock = fsockopen('tls://'.$host, $port, $errno, $errstr, 2); 

Full protocol specification: https://tools.ietf.org/rfc/rfc6455.txt

+9
source

UPDATE 2019: many servers require the key to be more unique than the original example, which made it impossible to establish a connection for the update. Key generation has now changed accordingly.

Your title should contain:

 Sec-WebSocket-Key: (some value) Sec-WebSocket-Version: 13 

for successful connection.
When you have established the connection, you also need to use hybi10 frame encoding.
See: https://tools.ietf.org/rfc/rfc6455.txt - It's a bit dry.

I made this working example:

 <?php $sp=websocket_open('127.0.0.1/ws_request.php?param=php_test',$errstr); websocket_write($sp,"Websocket request message"); echo websocket_read($sp,true); $sp=websocket_open('127.0.0.1:8080/ws_request.php?param=php_test',$errstr); websocket_write($sp,"Websocket request message"); echo websocket_read($sp,true); function websocket_open($url){ $key=base64_encode(openssl_random_pseudo_bytes(16)); $query=parse_url($url); $header="GET / HTTP/1.1\r\n" ."pragma: no-cache\r\n" ."cache-control: no-cache\r\n" ."Upgrade: WebSocket\r\n" ."Connection: Upgrade\r\n" ."Sec-WebSocket-Key: $key\r\n" ."Sec-WebSocket-Version: 13\r\n" ."\r\n"; $sp=fsockopen($query['host'],$query['port'], $errno, $errstr,1); if(!$sp) die("Unable to connect to server ".$url); // Ask for connection upgrade to websocket fwrite($sp,$header); stream_set_timeout($sp,5); $reaponse_header=fread($sp, 1024); if(!strpos($reaponse_header," 101 ") || !strpos($reaponse_header,'Sec-WebSocket-Accept: ')){ die("Server did not accept to upgrade connection to websocket" .$reaponse_header); } return $sp; } function websocket_write($sp, $data,$final=true){ // Assamble header: FINal 0x80 | Opcode 0x02 $header=chr(($final?0x80:0) | 0x02); // 0x02 binary // Mask 0x80 | payload length (0-125) if(strlen($data)<126) $header.=chr(0x80 | strlen($data)); elseif (strlen($data)<0xFFFF) $header.=chr(0x80 | 126) . pack("n",strlen($data)); elseif(PHP_INT_SIZE>4) // 64 bit $header.=chr(0x80 | 127) . pack("Q",strlen($data)); else // 32 bit (pack Q dosen't work) $header.=chr(0x80 | 127) . pack("N",0) . pack("N",strlen($data)); // Add mask $mask=pack("N",rand(1,0x7FFFFFFF)); $header.=$mask; // Mask application data. for($i = 0; $i < strlen($data); $i++) $data[$i]=chr(ord($data[$i]) ^ ord($mask[$i % 4])); return fwrite($sp,$header.$data); } function websocket_read($sp,$wait_for_end=true,&$err=''){ $out_buffer=""; do{ // Read header $header=fread($sp,2); if(!$header) die("Reading header from websocket failed"); $opcode = ord($header[0]) & 0x0F; $final = ord($header[0]) & 0x80; $masked = ord($header[1]) & 0x80; $payload_len = ord($header[1]) & 0x7F; // Get payload length extensions $ext_len = 0; if($payload_len >= 0x7E){ $ext_len = 2; if($payload_len == 0x7F) $ext_len = 8; $ext=fread($sp,$ext_len); if(!$ext) die("Reading header extension from websocket failed"); // Set extented paylod length $payload_len= 0; for($i=0;$i<$ext_len;$i++) $payload_len += ord($header[$i]) << ($ext_len-$i-1)*8; } // Get Mask key if($masked){ $mask=fread($sp,4); if(!$mask) die("Reading header mask from websocket failed"); } // Get payload $frame_data=''; do{ $frame= fread($sp,$payload_len); if(!$frame) die("Reading from websocket failed."); $payload_len -= strlen($frame); $frame_data.=$frame; }while($payload_len>0); // if opcode ping, reuse headers to send a pong and continue to read if($opcode==9){ // Assamble header: FINal 0x80 | Opcode 0x02 $header[0]=chr(($final?0x80:0) | 0x0A); // 0x0A Pong fwrite($sp,$header.$ext.$mask.$frame_data); // Recieve and unmask data }elseif($opcode<3){ $data=""; if($masked) for ($i = 0; $i < $data_len; $i++) $data.= $frame_data[$i] ^ $mask[$i % 4]; else $data.= $frame_data; $out_buffer.=$data; } // wait for Final }while($wait_for_end && !$final); return $out_buffer; } 

You can get the full version here: https://github.com/paragi/PHP-websocket-client

+6
source

Connect to a WSS stream using only php:

A public binance wss api example .

 <?php $sock = stream_socket_client("ssl://stream.binance.com:9443",$error,$errnum,30,STREAM_CLIENT_CONNECT,stream_context_create(null)); if (!$sock) { echo "[$errnum] $error" . PHP_EOL; } else { echo "Connected - Do NOT get rekt!" . PHP_EOL; fwrite($sock, "GET / stream?streams=btcusdt@kline _1m HTTP/1.1\r\nHost: stream.binance.com:9443\r\nAccept: */*\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: ".rand(0,999)."\r\n\r\n"); while (!feof($sock)) { var_dump(explode(",",fgets($sock, 512))); } } 
0
source

All Articles