当前位置:网站首页>Implementation of websocket long connection by workman under laravel

Implementation of websocket long connection by workman under laravel

2022-06-25 04:52:00 Kiway.

Laravel Next Workerman Realization websocket A long connection

  • install workerman
composer require workerman/workerman -vvv 
  • establish laravel Custom command
php artisan make:command Workerman

After executing this command, the \app\Console\Commands Generate under folder Workerman.php file

  • Workerman.php File code :
<?php
    namespace App\Console\Commands;
    use Workerman\Worker;
    use Illuminate\Console\Command;
    class Workerman extends Command {
    
        private $server;
        // -d  Whether or not to debug Way to run 
        protected $signature = 'workerman {action} {-d?}';
        protected $description = 'Start a Workerman server.';
        
        public function __construct() {
    
            parent::__construct();
            
        }

        /** * Execute the console command. * * @return mixed */
        public function handle() {
    
            global $argv;

            $context = array(
                //  more ssl Please refer to the manual for options  http://php.net/manual/zh/context.ssl.php
                'ssl' => array(
            
                    //  Please use absolute path 
            
                    'local_cert'                 => '/www/server/panel/vhost/cert/www.example.com/fullchain.pem', //  It can also be crt file 
            
                    'local_pk'                   => '/www/server/panel/vhost/cert/www.example.com/privkey.pem',
            
                    'verify_peer'                => false,
            
                    // 'allow_self_signed' => true, // If it is a self signed certificate, you need to turn on this option 
            
                )
            
            );
        
            //  The setting here is websocket agreement ( Any port , But you need to ensure that it is not occupied by other programs )
        
            $worker = new Worker('websocket://0.0.0.0:2000', $context);
            
            //  Set up transport Turn on ssl,websocket+ssl namely wss
            
            $worker->transport = 'ssl';
            
            // $worker->onMessage = function($con, $msg) {
    
        
            // $con->send('ok');
                
            // };
            $this->server = $worker;
            // $this->server = new Worker("websocket://0.0.0.0:2000");
            $arg = $this->argument('action');
            $argv[1] = $argv[2];
            $argv[2] = isset($argv[3]) ? "-{
      $argv[3]}" : '';

            switch ($arg) {
    
                case 'start':
                    $this->start();
                    break;
                case 'stop':
                    $this->stop();
                    break;
                case 'restart':
                    $this->restart();
                    break;
                case 'reload':
                    $this->reload();
                    break;
            }
        }
        private function start() {
    
            //  start-up 4 Two processes provide services to the outside world 
            $this->server->count = 4;
            $handler = \App::make('handlers\WorkermanHandler');
             //  Call back when connecting 
            $this->server->onConnect = [$handler, 'onConnect'];
             //  Callback when receiving client information 
            $this->server->onMessage = [$handler, 'onMessage'];
             //  Callback after process startup 
            $this->server->onWorkerStart = [$handler, 'onWorkerStart'];
             //  Callback triggered when disconnected 
            $this->server->onClose = [$handler, 'onClose'];
             //  function worker
            Worker::runAll();
        }

        private function stop() {
    
            $worker = $this->server;
            //  Set this instance to receive reload Whether the signal is reload restart 
            $worker->reloadable = false;
            $worker->onWorkerStop = function($worker)
            {
    
                echo "Worker reload...\n";
            };
            //  function worker
            Worker::runAll();
        }
        private function restart() {
    
            $worker = $this->server;
            //  Set this instance to receive reload Whether the signal is reload restart 
            $worker->reloadable = true;
            $worker->onWorkerStart = function($worker)
            {
    
                echo "Worker restart...\n";
            };
            //  function worker
            Worker::runAll();
        }
        private function reload() {
    
            $worker = $this->server;
            //  Set this instance to receive reload Whether the signal is reload restart 
            $worker->reloadable = false;
            $worker->onWorkerStart = function($worker)
            {
    
                echo "Worker reload...\n";
            };
            //  function worker
            Worker::runAll();
        }
    }`

  • workerman Referenced execution file

app\Console\Commands\handlers\WorkermanHandler.php file

<?php
    namespace handlers;
    use Workerman\Lib\Timer;
    use Illuminate\Support\Facades\Redis;
    use App\Log\LogController;

    //  Heartbeat interval 10 second 
    define('HEARTBEAT_TIME',100);

    class WorkermanHandler {
    
        const check = 0;

        //  Handles client connections 
        public function onConnect($connection) {
    
            echo " Link successful ";
        }
        public function editLog($function,$param,$res){
    
            $log=new LogController();
            // if($this->log == '1'){
    
                $log->Success(' Interface :'.$function.'; Upload parameters are as follows :'.json_encode($param).'; Returns the parameter :'.json_encode($res));
            // }
        }
        // public function onMessage($connection, $data) {
    
        // $connection->send($data);
        // }
        //  Processing client messages 
        public function onMessage($connection, $data) {
    
            $this->editLog($function='onMessage',$data,'');
            // The time when the last data uploaded is obtained 
            $connection->lastMessageTime = time();
            // $connection->send($data);
            //  Heartbeat bag 
            if($data!='{"t2yp3e":"213213","sae1acr213et":"sadasdas"}'){
    
                //RSA Decrypt 
                if(self::check == 1){
    
                        $myfile = fopen("rsa/rsa_private_key.pem", "r") or die("Unable to open file!");
                        $private_key = fread($myfile,filesize("rsa/rsa_private_key.pem"));
                        $pi_key =  openssl_pkey_get_private($private_key);
                        $encrypted = str_replace(' ', '+',$data);
                        $decrypted = ""; 
                        //  Decrypt 
                        openssl_private_decrypt(base64_decode($encrypted),$decrypted,$pi_key);// Private key decryption 
                        fclose($myfile);
                        // Decryption content is empty 
                        if($decrypted==''){
    
                            $connection->send(' Validation failed '); 
                            
                        }
                        // $connection->send($decrypted);
                        // Array parameter 
                        $data = json_decode($decrypted); 
                        $this->editLog($function='onMessage',$data,'');
                    
                }else{
    
                    // Test with 
                    $connection->send($data); 
                    $data = json_decode($data);
                }
            }else{
    
                $connection->send($data); 
                $data='';
            }
            
            if($data!=''){
    
                // Do what you want to do 
            }
            
            // Fault code 
            if(!empty($data->code)){
    
                // Do what you want to do 
            }
            
            //  Record speed and other data ( Details are activated ) Negligible 
            if(!empty($data->bluetooth)){
    
                $key_detail = 'detail'.$data->bluetooth;
                $detail = Redis::get($key_detail);
                if($detail){
    
                    // The data of the graph 
                    $key_curve = $data->bluetooth.'curve';
                    $curve = Redis::get($key_curve);
                    if(!empty($curve)){
    
                        $curve = unserialize($curve);
                        // echo json_encode($curve);
                        // How many elements the array is full will automatically clear the first element 
                        // if(count($curve)>5){
    
                        // array_shift($curve);
                        // }
                         array_push($curve,['speed'=>$data->speed??'0','voltage'=>$data->voltage??'0','electric_current'=>$data->current??'0','output_power'
                        =>$data->outpower??'0','Motherboardtemperature'=>$data->mTemperature??'0','Motortemperature'=>$data->eTemperature??'0','createtime'=>date('Y-m-d H:i:s',time())]);
                        Redis::setex($key_curve, 10, serialize($curve));
                    }else{
    
                        $curve = array();
                         array_push($curve,['speed'=>$data->speed??'0','voltage'=>$data->voltage??'0','electric_current'=>$data->current??'0','output_power'
                        =>$data->outpower??'0','Motherboardtemperature'=>$data->mTemperature??'0','Motortemperature'=>$data->eTemperature??'0','createtime'=>date('Y-m-d H:i:s',time())]);
                        Redis::setex($key_curve, 10, serialize($curve));
                    }
                }else{
    
                    echo 'detail is not';
                }

                $open = Redis::get($data->bluetooth.'open');
                if($open == '1'){
    
                    $export = Redis::get($data->bluetooth.'export');
                    if(!empty($export)){
    
                        $export = unserialize($export);
                         array_push($curve,['speed'=>$data->speed??'0','voltage'=>$data->voltage??'0','electric_current'=>$data->current??'0','output_power'
                        =>$data->outpower??'0','Motherboardtemperature'=>$data->mTemperature??'0','Motortemperature'=>$data->eTemperature??'0','createtime'=>date('Y-m-d H:i:s',time())]);
                        Redis::setex($data->bluetooth.'export', 300, serialize($export)); 
                    }else{
    
                        $export = array();
                         array_push($curve,['speed'=>$data->speed??'0','voltage'=>$data->voltage??'0','electric_current'=>$data->current??'0','output_power'
                        =>$data->outpower??'0','Motherboardtemperature'=>$data->mTemperature??'0','Motortemperature'=>$data->eTemperature??'0','createtime'=>date('Y-m-d H:i:s',time())]);
                        Redis::setex($data->bluetooth.'export', 300, serialize($export)); 
                    }
                }
                
            }

            //  Activation details ( Request for details websocket Trigger when )mTemperature
            if(!empty($data->bluetooth)){
    
                $key_detail = 'detail'.$data->bluetooth;// by 1 when , The graph stores data such as speed 
                Redis::setex($key_detail,'10', 1);
                
               //  Obtain the speed and other data of the curve 
                $key_curve = $data->bluetooth.'curve';
                $curve = Redis::get($key_curve);
                $connection->send(json_encode(unserialize($curve)));   
                
                
            }

            if(!empty($id)){
    
                if(!empty($data->code)&&$data->code!=''){
    
                    \DB::table('dlc_websocket')->where('id',$id)->update(['code'=>$data->code]);
                }
                //id assignment 
                $connection->id = $id;
            }
            // }
        }

        //  Handle client disconnects 
        public function onClose($connection) {
    
            echo "connection closed from ip {
      $connection->getRemoteIp()}\n";
        }

        public function onWorkerStart($worker) {
    
            Timer::add(1, function () use ($worker) {
    
                $time_now = time();
                foreach ($worker->connections as $connection) {
    
                    //  It's possible that connection I haven't heard from you yet , be lastMessageTime Set to current time 
                    if (empty($connection->lastMessageTime)) {
    
                        $connection->lastMessageTime = $time_now;
                        continue;
                    }
                    //  The last communication interval is greater than the heartbeat interval , The client is considered offline , Close the connection 
                    if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
    
                        if($connection->id){
    
                            \DB::table('dlc_websocket')->where('id',$connection->id)->delete();
                            // \DB::table('dlc_websocket')->where('id',$connection->id)->update(['status'=>0]);
                        }
                        // Callback after disconnection 
                        echo "Client ip {
      $connection->getRemoteIp()} timeout!!!\n"; $connection->close();
                    }
                }
            });
            
        }
    }

The first file is the configuration workerman Basic information of , You can configure the https, The long connection will be wss instead of ws. The second file is used to process the received data , For example, for storage , Front end page drawing display, etc .

  • start-up workerman
php artisan Workerman start d
  • close workerman
php artisan Workerman stop d
原网站

版权声明
本文为[Kiway.]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202210533123293.html