websocket php客户端,PHP WebSocket 客户端类 WebSocketClient

* @version 2011-10-18 */class WebSocketClient{private $_host;private $_port;private $_path;private $_origin;private $_Socket = null;private $_connected = false;public function __construct() { }public function __destruct(){$this->disconnect();}public function sendData($data, $type = 'text', $masked = true){if($this->_connected === false){trigger_error("Not connected", E_USER_WARNING);return false;}if( !is_string($data)) {trigger_error("Not a string data was given.", E_USER_WARNING);return false;}if (strlen($data) == 0){return false;}$res = @fwrite($this->_Socket, $this->_hybi10Encode($data, $type, $masked));if($res === 0 || $res === false){return false;}$buffer = ' ';while($buffer !== ''){$buffer = fread($this->_Socket, 512);}return true;}public function connect($host, $port, $path, $origin = false){$this->_host = $host;$this->_port = $port;$this->_path = $path;$this->_origin = $origin;$key = base64_encode($this->_generateRandomString(16, false, true));$header = "GET " . $path . " HTTP/1.1\r\n";$header.= "Host: ".$host.":".$port. "\r\n";$header.= "Upgrade: websocket\r\n";$header.= "Connection: Upgrade\r\n";//$header.= "Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n";$header.= "Sec-WebSocket-Key: " . $key . "\r\n";if($origin !== false){$header.= "Sec-WebSocket-Origin: " . $origin . "\r\n";}$header.= "Sec-WebSocket-Version: 13\r\n\r\n";$this->_Socket = fsockopen($host, $port, $errno, $errstr, 2);socket_set_timeout($this->_Socket, 2, 10000);//socket_write($this->_Socket, $header);$res = @fwrite($this->_Socket, $header);if( $res === false ){echo "fwrite false \n";}$response = @fread($this->_Socket, 1500);//$response = socket_read($this->_Socket);preg_match('#Sec-WebSocket-Accept:\s(.*)$#mU', $response, $matches);if ($matches) {$keyAccept = trim($matches[1]);$expectedResonse = base64_encode(pack('H*', sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));$this->_connected = ($keyAccept === $expectedResonse) ? true : false;}return $this->_connected;}public function checkConnection(){$this->_connected = false;// send ping:$data = 'ping?';@fwrite($this->_Socket, $this->_hybi10Encode($data, 'ping', true));$response = @fread($this->_Socket, 300);if(empty($response)){return false;}$response = $this->_hybi10Decode($response);if(!is_array($response)){return false;}if(!isset($response['type']) || $response['type'] !== 'pong'){return false;}$this->_connected = true;return true;}public function disconnect(){$this->_connected = false;is_resource($this->_Socket) and fclose($this->_Socket);}public function reconnect(){sleep(10);$this->_connected = false;fclose($this->_Socket);$this->connect($this->_host, $this->_port, $this->_path, $this->_origin);}private function _generateRandomString($length = 10, $addSpaces = true, $addNumbers = true){ $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"ยง$%&/()=[]{}';$useChars = array();// select some random chars: for($i = 0; $i < $length; $i++){$useChars[] = $characters[mt_rand(0, strlen($characters)-1)];}// add spaces and numbers:if($addSpaces === true){array_push($useChars, ' ', ' ', ' ', ' ', ' ', ' ');}if($addNumbers === true){array_push($useChars, rand(0,9), rand(0,9), rand(0,9));}shuffle($useChars);$randomString = trim(implode('', $useChars));$randomString = substr($randomString, 0, $length);return $randomString;}private 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:$framePayload = array();for($i = 0; $i < $payloadLength; $i++){$frame .= ($masked === true) ? $payload[$i] ^ $mask[$i % 4] : $payload[$i];}return $frame;}private function _hybi10Decode($data){$payloadLength = '';$mask = '';$unmaskedPayload = '';$decodedData = array();// estimate frame type:$firstByteBinary = sprintf('%08b', ord($data[0]));$secondByteBinary = sprintf('%08b', ord($data[1]));$opcode = bindec(substr($firstByteBinary, 4, 4));$isMasked = ($secondByteBinary[0] == '1') ? true : false;$payloadLength = ord($data[1]) & 127;switch($opcode){// text frame:case 1:$decodedData['type'] = 'text';break;case 2:$decodedData['type'] = 'binary';break;// connection close frame:case 8:$decodedData['type'] = 'close';break;// ping frame:case 9:$decodedData['type'] = 'ping';break;// pong frame:case 10:$decodedData['type'] = 'pong';break;default:return false;break;}if($payloadLength === 126){ $mask = substr($data, 4, 4); $payloadOffset = 8; $dataLength = bindec(sprintf('%08b', ord($data[2])) . sprintf('%08b', ord($data[3]))) + $payloadOffset;}elseif($payloadLength === 127){$mask = substr($data, 10, 4);$payloadOffset = 14;$tmp = '';for($i = 0; $i < 8; $i++){$tmp .= sprintf('%08b', ord($data[$i+2]));}$dataLength = bindec($tmp) + $payloadOffset;unset($tmp);}else{$mask = substr($data, 2, 4);$payloadOffset = 6;$dataLength = $payloadLength + $payloadOffset;}if($isMasked === true){for($i = $payloadOffset; $i < $dataLength; $i++){$j = $i - $payloadOffset;if(isset($data[$i])){$unmaskedPayload .= $data[$i] ^ $mask[$j % 4];}}$decodedData['payload'] = $unmaskedPayload;}else{$payloadOffset = $payloadOffset - 4;$decodedData['payload'] = substr($data, $payloadOffset);}return $decodedData;}}

使用示例: // 使用 WebSocket 通知客户端$client = new \Common\Library\WebSocketClient();$client->connect($_SERVER['HTTP_HOST'], 943, '/');$payload = json_encode(array('code' => 'xxx','id' => '1'));$rs = $client->sendData($payload);if( $rs !== true ){echo "sendData error...\n";}else{echo "ok\n";}

来自: http://my.oschina.net/skq/blog/552923

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值