使用php创建WebSocket服务

来源:互联网 发布:安卓看图软件 编辑:程序博客网 时间:2024/06/15 05:23
执行方法:
首先先修改server.php与index.html的ip
通过命令行执行 [php路径]php.exe "[文件路径]server.php"
然后通过浏览器打开index.html

<?include 'websocket.class.php';$config=array('address'=>'192.168.0.200','port'=>'8000','event'=>'WSevent',//回调函数的函数名'log'=>true,);$websocket = new websocket($config);$websocket->run();function WSevent($type,$event){ global $websocket;if('in'==$type){$websocket->log('客户进入id:'.$event['k']);}elseif('out'==$type){$websocket->log('客户退出id:'.$event['k']);}elseif('msg'==$type){$websocket->log($event['k'].'消息:'.$event['msg']);roboot($event['sign'],$event['msg']);}}function roboot($sign,$t){ global $websocket; switch ($t){ case 'hello': $show='hello,GIt @ OSC';break; case 'name':$show='Robot';break; case 'time': $show='当前时间:'.date('Y-m-d H:i:s');break; case '再见': $show='( ^_^ )/~~拜拜';$websocket->write($sign,'Robot:'.$show);$websocket->close($sign);return;break; case '天王盖地虎': $array = array('小鸡炖蘑菇','宝塔震河妖','粒粒皆辛苦'); $show = $array[rand(0,2)];break;default: $show='( ⊙o⊙?)不懂,你可以尝试说:hello,name,time,再见,天王盖地虎.';}$websocket->write($sign,'Robot:'.$show);}?>
<?phpclass websocket{ public $log; public $event; public $signets; public $users;  public $master;  public function __construct($config){ if (substr(php_sapi_name(), 0, 3) !== 'cli') {die("请通过命令行模式运行!");}error_reporting(E_ALL);set_time_limit(0);ob_implicit_flush(); $this->event = $config['event']; $this->log = $config['log']; $this->master=$this->WebSocket($config['address'], $config['port']);$this->sockets=array('s'=>$this->master);} function WebSocket($address,$port){ $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1); socket_bind($server, $address, $port);socket_listen($server); $this->log('开始监听: '.$address.' : '.$port); return $server;} function run(){while(true){$changes=$this->sockets;@socket_select($changes,$write=NULL,$except=NULL,NULL); foreach($changes as $sign){if($sign==$this->master){$client=socket_accept($this->master);$this->sockets[]=$client; $user = array('socket'=>$client,'hand'=>false,); $this->users[] = $user;$k=$this->search($client); $eventreturn = array('k'=>$k,'sign'=>$sign);$this->eventoutput('in',$eventreturn);}else{$len=socket_recv($sign,$buffer,2048,0);$k=$this->search($sign);$user=$this->users[$k];if($len<7){$this->close($sign); $eventreturn = array('k'=>$k,'sign'=>$sign);$this->eventoutput('out',$eventreturn);continue;}if(!$this->users[$k]['hand']){//没有握手进行握手$this->handshake($k,$buffer);}else{ $buffer = $this->uncode($buffer); $eventreturn = array('k'=>$k,'sign'=>$sign,'msg'=>$buffer);$this->eventoutput('msg',$eventreturn);}}}}} function search($sign){//通过标示遍历获取id foreach ($this->users as $k=>$v){if($sign==$v['socket']) return $k;} return false;} function close($sign){//通过标示断开连接 $k=array_search($sign, $this->sockets);socket_close($sign);unset($this->sockets[$k]);unset($this->users[$k]);} function handshake($k,$buffer){ $buf = substr($buffer,strpos($buffer,'Sec-WebSocket-Key:')+18); $key = trim(substr($buf,0,strpos($buf,"rn"))); $new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true)); $new_message ="HTTP/1.1 101 Switching Protocolsrn"; $new_message .="Upgrade: websocketrn"; $new_message .="Sec-WebSocket-Version: 13rn"; $new_message .="Connection: Upgradern"; $new_message .="Sec-WebSocket-Accept:". $new_key ."rnrn";socket_write($this->users[$k]['socket'],$new_message,strlen($new_message));$this->users[$k]['hand']=true; return true;} function uncode($str){ $mask = array();  $data = '';  $msg = unpack('H*',$str);  $head = substr($msg[1],0,2);  if (hexdec($head{1}) === 8) {  $data = false;  }else if (hexdec($head{1}) === 1){  $mask[] = hexdec(substr($msg[1],4,2)); $mask[] = hexdec(substr($msg[1],6,2)); $mask[] = hexdec(substr($msg[1],8,2)); $mask[] = hexdec(substr($msg[1],10,2)); $s = 12;  $e = strlen($msg[1])-2;  $n = 0;  for ($i=$s; $i<= $e; $i+= 2) {  $data .= chr($mask[$n%4]^hexdec(substr($msg[1],$i,2))); $n++;}} return $data;} function code($msg){ $msg = preg_replace(array('/r$/','/n$/','/rn$/',), '', $msg); $frame = array();  $frame[0] = '81';  $len = strlen($msg);  $frame[1] = $len<16?'0'.dechex($len):dechex($len); $frame[2] = $this->ord_hex($msg); $data = implode('',$frame); return pack("H*", $data);} function ord_hex($data) {  $msg = '';  $l = strlen($data);  for ($i= 0; $i<$l; $i++) {  $msg .= dechex(ord($data{$i})); } return $msg; } function idwrite($id,$t){//通过id推送信息 if(!$this->users[$id]['socket']){return false;}//没有这个标示$t=$this->code($t); return socket_write($this->users[$id]['socket'],$t,strlen($t));} function write($k,$t){//通过标示推送信息$t=$this->code($t); return socket_write($k,$t,strlen($t));} function eventoutput($type,$event){//事件回调call_user_func($this->event,$type,$event);} function log($t){//控制台输出if($this->log){$t=$t."rn"; fwrite(STDOUT, iconv('utf-8','gbk//IGNORE',$t));}}}