websocket 应用实例

来源:互联网 发布:mac版软件下载工具 编辑:程序博客网 时间:2024/06/16 06:54

1. 服务端

class WebSocketServer{    public $server;    public function __construct($controller) {        $this->server = new \swoole_websocket_server("0.0.0.0", 9501);        $this->server->set(array(            'worker_num' => 8,            'daemonize' => false,//            'heartbeat_check_interval' => 30,//            'heartbeat_idle_time' => 90,            'heartbeat_check_interval' => 60,            'heartbeat_idle_time' => 600,        ));        $this->server->on('WorkerStart', array($controller, 'onWorkerStart'));        $this->server->on('open', array($controller, 'onOpen'));        $this->server->on('message',array($controller, 'onMessage') );        $this->server->on('close',array($controller, 'onClose') );        $this->server->on('request', array($controller, 'onRequest'));        $this->server->on('Timer', array($controller, 'onTimer'));    }    public function start(){        $this->server->start();    }}class ServerController extends Controller{    private $fdKey='swoole_websocket_server_fd';    private $userIdKey='swoole_websocket_server_userId';    const GPS_POINT_KEY = "GPS:GPSPOINT";   // 实时坐标点的标识    public function start()    {        try{            $server = new WebSocketServer($this);            $server->start();        }catch(\Exception $e) {            $this->log("websocket:Caught exception000:".$e->getMessage());        }    }    public function onWorkerStart( $server , $worker_id)    {        // 在Worker进程开启时绑定定时器        echo "onWorkerStart\n";        // 只有当worker_id为0时才添加定时器,避免重复添加        if ($worker_id == 0) {            $server->addtimer(1000);        }    }    public function onTimer($server, $interval) {        switch( $interval ) {            case 1000: {//                echo "Do Thing A at interval 30000\n";                $this->pushData($server);                break;            }        }    }    public function onOpen(\swoole_websocket_server $server, $request) {        echo "server: handshake success with fd{$request->fd}\n";        try{            $server = $request->server;            $uri = trim($server['request_uri'],'/');            $user = explode('/',$uri);            $userId = $user[1];            $redis = Cache::getInstance();            $fdArr = $redis->get($this->fdKey.$userId);            $fd = $request->fd;            if(!empty($fdArr)){                array_push($fdArr,$fd);                $newFdArr = $fdArr;            }else{                $newFdArr = array($fd);            }            $redis->set($this->fdKey.$userId,$newFdArr);            $redis->set($this->userIdKey.$fd,$userId);            $this->log("websocket:server start, fd:".$request->fd);        }catch(\Exception $e) {            $this->log("websocket:Caught exception000:".$e->getMessage());        }    }    public function onMessage(\swoole_websocket_server $server, $frame) {        echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";        try{           $data = $frame->data;           if($data=='close'){               $redis = Cache::getInstance();               $key = $this->userIdKey.$frame->fd;               $userId = $redis->get($key);               $redis->rm($key);               $redis->rm($this->fdKey.$userId);           }        }catch(\Exception $e){            $this->log("websocket:Caught exception111:".$e->getMessage());        }    }    public function onClose($ser,$fd) {        echo "client {$fd} closed\n";        $redis = Cache::getInstance();        $redis->rm('swoole_websocket_server_fd1');        $key = $this->userIdKey.$fd;        $userId = $redis->get($key);        $redis->rm($key);        $fdKey = $this->fdKey.$userId; //团队下的fd        $fdArr = $redis->get($fdKey);        if(!empty($fdArr)&&in_array($fd,$fdArr)){            $fd = arrray($fd);            $newFdArr = array_diff($fdArr,$fd);            if(!empty($newFdArr)){                $redis->set($fdKey,$newFdArr);            }else{                $redis->rm($fdKey);            }        }        $this->log("websocket:server close:".date("Y-m-d H:i:s"));    }    public function onRequest($request, $response) {        // 接收http请求从get获取message参数的值,给用户推送        // $this->server->connections 遍历所有websocket连接用户的fd,给所有用户推送        foreach ($this->server->connections as $fd) {            $this->server->push($fd, $request->get['message']);        }    }    public function pushData($server){        $redis = Cache::getInstance();        $all = $redis->hGetAll(self::GPS_POINT_KEY);        foreach($all as $key=>$val){            if(!empty($val)){                list($lonlat, $gateTime) = explode('|', $val);                list($lon, $lat) = explode(',', $lonlat);                $latitude = "$lat";                $longitude = "$lon";                if($gateTime+60>time()){//60s内的算坐标更新了                    if(strlen($key)==11){ //手机                        //取得对应在线手机所在的团队id                        $where = ['id_card'=>$key,'state'=>1];                    }elseif(strlen($key)==15){ //定位神器                        //取得对应在线手机所在的团队id                        $where = ['device_imei'=>$key,'state'=>1];                    }                    $deviceData = PointDeviceService::getOnlineDevice($where);                    $deviceData['record'] = [                        'gate_time'=>date("Y-m-d H:i:s", $gateTime),                        'latitude'=>$latitude,                        'longitude'=>$longitude,                    ];                    print_r($deviceData);                    $jsonData = json_encode($deviceData);                    echo $userId = $deviceData['user_id'];//团队ID                    $fdArr = $redis->get($this->fdKey.$userId);                    echo "aaa:";print_r($fdArr);                    if(!empty($fdArr)){                        foreach($fdArr as $fd){                            $server->push($fd,$jsonData);                        }                    }                    $this->log("websocket:server push data:".$jsonData);                }else{                    $this->log("websocket:".$key."设备没有更新的坐标数据");                }            }        }    }    private function log($message=''){        $trueDir = RUNTIME_PATH.'websocketServer'.DIRECTORY_SEPARATOR;        if(!is_dir($trueDir)){            mkdir($trueDir,0777,true);        }        $file = date('Y_m_d').'.log';        $trueFile = $trueDir.$file;        $message = date("Y-m-d H:i:s").":".$message;        file_put_contents($trueFile,$message.PHP_EOL,FILE_APPEND);    }}


2. 客户端

function wsConnect(){       // var userId = '{userId}';        var wsServer = 'ws://127.0.0.1:9501/user_id/1';        var websocket = new WebSocket(wsServer);        return websocket;    }    //在地图上动态显示所有在线设备 add by mzc 2017.10.19    function dynamicDisplay(){        websocket =  wsConnect();        websocket.onopen = function (evt) {            if(websocket.readyState==1){                websocket.send('user_id=1');                console.log("websocket连接成功");            }        };        websocket.onclose = function (evt) {            console.log("Disconnected");            if(websocket.readyState==3){                websocket.send('close');                wsConnect();                console.log('reconnect');            }        };        websocket.onmessage = function (evt) {            console.log('服务器推送过来的数据: ' + evt.data);            var data = evt.data;            data = eval('(' + data + ')');            var temp = [];//            for (var i = 0; i <data.length; i++) {//                temp.push(data[i]);//            }            temp.push(data);            openInfo(temp);        };        websocket.onerror = function (evt, e) {            console.log('Error occured: ' + evt.data);            if(websocket.readyState==3){                wsConnect();                console.log('reconnect');            }        };        //关闭页面时记得一定要关闭连接,否则服务端可能不会释放        window.onunload = function(){            websocket.close();        };    }


原创粉丝点击