Skip to content

Instantly share code, notes, and snippets.

@algomaster99
Created May 16, 2020 15:51
Show Gist options
  • Save algomaster99/b02a8723dc265f8e36c6830e378ade12 to your computer and use it in GitHub Desktop.
Save algomaster99/b02a8723dc265f8e36c6830e378ade12 to your computer and use it in GitHub Desktop.
Websocket Client in PHP
<?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