Heim > Backend-Entwicklung > PHP-Tutorial > PHP WebSocket 客户端类 WebSocketClient

PHP WebSocket 客户端类 WebSocketClient

WBOY
Freigeben: 2016-06-20 12:41:54
Original
1895 Leute haben es durchsucht

<?phpnamespace Common\Library;// ini_set('display_errors', 1);// error_reporting(E_ALL);/** * Very basic websocket client. * Supporting draft hybi-10.  *  * @author Simon Samtleben <web@lemmingzshadow.net> * @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;	}}
Nach dem Login kopieren


使用示例:

// 使用 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";		}
Nach dem Login kopieren


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

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage