Created
May 16, 2020 15:51
-
-
Save algomaster99/b02a8723dc265f8e36c6830e378ade12 to your computer and use it in GitHub Desktop.
Websocket Client in PHP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace common\components; | |
class WebSocketClient { | |
private $_Socket = null; | |
public function __construct($host, $port) { | |
$this->_connect($host, $port); | |
} | |
public function __destruct() { | |
$this->_disconnect(); | |
} | |
public function sendData($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)); | |
else $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($this->_Socket,$header.$data); | |
} | |
private function _connect($host='',$port=80,$headers='',&$error_string='',$timeout=10,$ssl=false){ | |
// Generate a key (to convince server that the update is not random) | |
// The key is for the server to prove it i websocket aware. (We know it is) | |
$key=base64_encode(openssl_random_pseudo_bytes(16)); | |
$header = "GET /ws/faculty_profile/cms/ HTTP/1.1\r\n" | |
."Host: $host\r\n" | |
."pragma: no-cache\r\n" | |
."Upgrade: WebSocket\r\n" | |
."Connection: Upgrade\r\n" | |
."Sec-WebSocket-Key: $key\r\n" | |
."Sec-WebSocket-Version: 13\r\n"; | |
// Add extra headers | |
if(!empty($headers)) foreach($headers as $h) $header.=$h."\r\n"; | |
// Add end of header marker | |
$header.="\r\n"; | |
// Connect to server | |
$host = $host ? $host : "127.0.0.1"; | |
$port = $port <1 ? 80 : $port; | |
$address = ($ssl ? 'ssl://' : '') . $host . ':' . $port; | |
$this->_Socket = stream_socket_client($address, $errno, $errstr, $timeout); | |
if(!$this->_Socket){ | |
$error_string = "Unable to connect to websocket server: $errstr ($errno)"; | |
return false; | |
} | |
// Set timeouts | |
stream_set_timeout($this->_Socket,$timeout); | |
//Request upgrade to websocket | |
$rc = fwrite($this->_Socket,$header); | |
if(!$rc){ | |
$error_string | |
= "Unable to send upgrade header to websocket server: $errstr ($errno)"; | |
return false; | |
} | |
// Read response into an assotiative array of headers. Fails if upgrade failes. | |
$reaponse_header=fread($this->_Socket, 1024); | |
// status code 101 indicates that the WebSocket handshake has completed. | |
if(!strpos($reaponse_header," 101 ") | |
|| !strpos($reaponse_header,'Sec-WebSocket-Accept: ')){ | |
$error_string = "Server did not accept to upgrade connection to websocket." | |
.$reaponse_header. E_USER_ERROR; | |
return false; | |
} | |
// The key we send is returned, concatenate with "258EAFA5-E914-47DA-95CA- | |
// C5AB0DC85B11" and then base64-encoded. one can verify if one feels the need... | |
return true; | |
} | |
private function _disconnect() { | |
fclose($this->_Socket); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment