執行方法: 首先先修改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);
- }
- ?>
複製代碼
- websocket_TEST
- <li>=======websocket======<li>
-
複製代碼
- /*
- 建立類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小貝) === 8) {
- $data = false;
- }else if (hexdec($head小貝) === 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));
- }
- }
- }
複製代碼 |