添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
我去  ·  python - ...·  3 年前    · 
lichail  ·  Connecting to ...·  3 年前    · 
lichail  ·  WebSocket client in ...·  3 年前    · 
lichail  ·  纯PHP实现的websocket客户端_zh ...·  3 年前    · 

I'm trying to connect a PHP-based client to a websocket server.

Here's the code I have been using which has been widely published on different forums. But for some reason I just cannot 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;

I would probably prefer to use an existing websocket client library (maybe https://github.com/gabrielbull/php-websocket-client or https://github.com/Devristo/phpws/tree/master/src/Devristo/Phpws/Client ?) rather than roll your own, but I got it to at least connect by using:

$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 is using TLS/SSL, so I also needed:

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

The full protocol spec is: https://tools.ietf.org/rfc/rfc6455.txt

Improve this answer Follow This response got me started in the right direction. With a little more searching of some other forums and tweaking of the header code, I discovered the following solution. ripple.com/forum/… I can confirm that it works! – John Whelan Mar 14 '14 at 17:36 That ripple.com post worked for me too! Link structure of the site must have changed. New link is here: forum.ripple.com/… – rgbflawed Jan 17 '17 at 16:46

UPDATE 2019: many servers requires the key to be more unique that the original example, resulting in failure to establish upgrade connection. The key generation is now changed accordingly.

Your header must contain:

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

to connect successfully.
When you have made the connection, you also need to use the hybi10 frame encoding.
See: https://tools.ietf.org/rfc/rfc6455.txt - Its a bit dry though.

I have made this working example:

$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=""; // 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=''; $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]; $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

Improve this answer Follow "Event server did not accept to upgrade connection to websocket." What to do ? – user494599 Apr 13 '16 at 12:20 That depends on your setup and the response from the server. You can print out $reaponse_header and see if i gives a clue. Does your webserver support websockets on the port you use? – Simon Rigét Apr 14 '16 at 19:13 I'm having a problem where it can't connect as well not sure why yet. I'm using newest code from the github. – Joseph Astrahan Mar 30 '17 at 5:03 Server did not accept to upgrade connection to websocket.HTTP/1.1 400 Bad Request X-Powered-By: Ratchet/0.3.6 256, in my case attempting to connect to localhost websocket sever ratchet – Joseph Astrahan Mar 30 '17 at 5:06 The code on github runs in production. Please don't use the comments for troubleshooting your application. You are welcome to drop a mail to me. if there is a problem with the code. Please make sure there is a testable setup :) – Simon Rigét Apr 3 '17 at 8:24

Example with the public binance wss api.

$sock = stream_socket_client("tls://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)));

More details: WebSockets - send json data via php

Improve this answer Follow

https://github.com/ratchetphp/Pawl

I tried around 10 different solutions from various stackoverflow threads but nothing worked, after spending about 6 hours trying different solution this worked for me. scenario: Ratchet as server I was able to connect via reactjs I wasn't able to connect via php, Expected Result: To send message from php-client to all connected react clients. the git repo i provided was a lucky break i was looking for.

Improve this answer Follow

The 400 error is because you're missing Host and Origin in the header.

$key=base64_encode(openssl_random_pseudo_bytes(16));
$query=parse_url($url);
$local = "http://".$query['host'];
if (isset($_SERVER['REMOTE_ADDR'])) $local = "http://".$_SERVER['REMOTE_ADDR'];  
$header="GET / HTTP/1.1\r\n"
    ."Host: ".$query['host']."\r\n"
    ."Origin: ".$local."\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";
        
            
                    Improve this answer
                Follow