请选择 进入手机版 | 继续访问电脑版
虚位以待    招租QQ:244594752    尺寸:960x60
终身VIP需技术指导请加(官方QQ :244594752 )
加入我们,终身VIP只需159元,全站下载(老客户请联系我补差价即可升级)
查看: 253|回复: 1

使用php创建WebSocket服务

[复制链接]

该用户从未签到

2243

主题

2275

帖子

7827

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
7827
发表于 2018-6-1 22:29:47 | 显示全部楼层 |阅读模式
执行方法:
首先先修改server.php与index.html的ip
通过命令行执行 [php路径]\php.exe "[文件路径]\server.php"

然后通过浏览器打开index.html


server.php





  • <?php  
  • 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);  
  • }  
  • ?>  




index.html



  • <!doctype html>  
  • <html>  
  • <head>  
  • <meta charset="utf-8">  
  • <title>websocket_TEST</title>  
  • </head>  
  • <body>  
  • <textarea class="log" style="width: 100%; height: 500px;">  
  • =======websocket======  
  • </textarea>  
  • <input type="button" value="连接">   
  • <input type="button" value="断开">  
  • <input type="text" id="text">  
  • <input type="button" value="发送">  
  • <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>  
  • <script>  
  • function link(){  
  •   var url='ws://192.168.0.200:8000';  
  •   socket=new WebSocket(url);  
  •   socket.onopen=function(){log('连接成功')}  
  •   socket.onmessage=function(msg){log('获得消息:'+msg.data);console.log(msg);}  
  •   socket.onclose=function(){log('断开连接')}  
  • }  
  • function dis(){  
  •   socket.close();  
  •   socket=null;  
  • }  
  • function log(var1){  
  •   $('.log').append(var1+"\r\n");  
  • }  
  • function send(){  
  •   socket.send($('#text').attr('value'));  
  • }  
  • function send2(){  
  •   var json = JSON.stringify({'type':'php','msg'('#text2').attr('value')})  
  •   socket.send(json);  
  • }  
  • </script>  
  • </body>  
  • </html>  





websocket.class.php



  • <?php  
  • /*
  • 创建类websocket($config);
  • $config结构:
  • $config=array(
  •   'address'=>'192.168.0.200',//绑定地址
  •   'port'=>'8000',//绑定端口
  •   'event'=>'WSevent',//回调函数的函数名
  •   'log'=>true,//命令行显示记录
  • );
  •   
  • 回调函数返回数据格式
  • function WSevent($type,$event)
  •   
  • $type字符串 事件类型有以下三种
  • in  客户端进入
  • out 客户端断开
  • msg 客户端消息到达
  • 均为小写
  •   
  • $event 数组
  • $event['k']内置用户列表的userid;
  • $event['sign']客户标示
  • $event['msg']收到的消息 $type='msg'时才有该信息
  •   
  • 方法:
  • run()运行
  • search(标示)遍历取得该标示的id
  • close(标示)断开连接
  • write(标示,信息)推送信息
  • idwrite(id,信息)推送信息
  •   
  • 属性:
  • $users 客户列表
  • 结构:
  • $users=array(
  • [用户id]=>array('socket'=>[标示],'hand'=[是否握手-布尔值]),
  • [用户id]=>arr.....
  • )
  • */  
  •    
  • class 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,"\r\n")));  
  •     $new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));  
  •     $new_message = "HTTP/1.1 101 Switching Protocols\r\n";  
  •     $new_message .= "Upgrade: websocket\r\n";  
  •     $new_message .= "Sec-WebSocket-Version: 13\r\n";  
  •     $new_message .= "Connection: Upgrade\r\n";  
  •     $new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";  
  •     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$/','/\r\n$/',), '', $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."\r\n";  
  •         fwrite(STDOUT, iconv('utf-8','gbk//IGNORE',$t));  
  •       }  
  •     }  
  • }  


回复

使用道具 举报

该用户从未签到

0

主题

180

帖子

366

积分

禁止发言

积分
366
发表于 2018-8-23 03:57:33 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|妙想源码社区 积分提现

GMT+8, 2018-12-15 07:59 , Processed in 1.092120 second(s), 24 queries .

Powered by Discuz! X3.2 Licensed

© 2001-2020 Comsenz Inc.

快速回复 返回顶部 返回列表
 
FDGDF
客服QQ 妙想科技 244594752
【旺旺】 点击这里给我发消息
【邮箱】
244594752@qq.com
【地址】 湖南省常德市武陵区三姑巷77
【妙想科技】 【9188qhl.com】