laravel使用workerman 用户交互、服务器交互

使用 workeman 实现浏览器相互通信、服务器浏览器交互


一、安装 workerman

composer require workerman/workerman

二、生成命令文件

php artisan make:command Workerman

修改文件


<?php

namespace App\Console\Commands;


use Illuminate\Console\Command;

use Workerman\Worker;

class Workerman extends Command

{

    protected $signature = 'Workerman {action} {--daemonize}';

    protected $description = 'Command description';

    public function __construct()

    {

        parent::__construct();

    }

    public function handle()

    {

        global $argv;//定义全局变量

        $arg = $this->argument('action');

        $argv[1] = $arg;

        $argv[2] = $this->option('daemonize') ? '-d' : '';//该参数是以daemon(守护进程)方式启动


        global $text_worker;

        // 创建一个Worker监听2345端口,使用websocket协议通讯

        $text_worker = new Worker("websocket://0.0.0.0:2345");

        $text_worker->uidConnections = array();//在线用户连接对象

        $text_worker->uidInfo = array();//在线用户的用户信息

        // 启动4个进程对外提供服务

        $text_worker->count = 4;

        //当启动workerman的时候 触发此方法

        $text_worker->onWorkerStart =function(){


        };

        //当浏览器连接的时候触发此函数

        $text_worker->onConnect = function($connection){


        };

        //向用户发送信息的时候触发

        //$connection 当前连接的人的信息 $data 发送的数据

        $text_worker->onMessage = function($connection,$data){


        };

        //浏览器断开链接的时候触发

        $text_worker->onClose = function($connection){};

        Worker::runAll();

    }

}

三、启动命令

$ php artisan Workerman start 

Deprecated: Directive 'track_errors' is deprecated in Unknown on line 0

----------------------- WORKERMAN -----------------------------

Workerman version:4.0.19          PHP version:7.2.9

------------------------ WORKERS -------------------------------

worker               listen                              processes status

none                 websocket://0.0.0.0:2345            4         [ok]

四、浏览器之间通信

1. HTML 代码 两个 html 做交互

 var socket = new WebSocket("ws://localhost:2345//ws");

         // 建立连接时触发 建立链接的时候,需要向workerman发送一条指令,告诉他我是谁,使用id或者用户标识作为uid,告诉workerman 例如,当前html 用户id是37

         socket.onopen = function(event) {

            console.log('连接开始...');

            socket.send('{"uid":36,"type":'login'}');

         }

         //workerman发送消息的时候,接收并打印

         socket.onmessage = function(event) {

            var msg = event.data;

            console.log(msg );

         }

2. 设置 uid

浏览器发来了用户 uid,需要 workerman 保留一下,网上有文档说在触发的时候保存,还有用 session 的,我试验了没成功,所有用浏览器建立链接的时候,向 workerman 发送一条信息来创建 uid,在 workerman 上接收一下


//$connection 当前连接的人的信息 $data 发送的数据

$text_worker->onMessage = function($connection,$data){

      $data = json_decode($data);

      if($data['type']=='login'){

         $this->create_uid($connection,$data);

      }

};

//创建uid方法

 public function create_uid($connection,$data){

        global $text_worker;

        $connection->uid = $data['uid'];

        //保存用户的uid

        $text_worker->uidConnections["{$connection->uid}"] = $connection;

        //向自己的浏览器返回创建成功的信息

        $connection->send("用户:[{$connection->uid}] 创建成功");

    }

这时候浏览器就会出现打印信息




3. 向其他用户发送信息

向用户 uid 是 37 的浏览器发送信息


//js代码

 socket.send('{"type":"login","to_uid":36,"uid":36,"message":"nihao"}');

 //workerman 

 //$connection 当前连接的人的信息 $data 发送的数据

        $text_worker->onMessage = function($connection,$data){

            $data = json_decode($data,true);

            var_dump($data);

            if($data['type']=='login'){

                $this->create_uid($connection,$data);

            }

            if($data['type']=='send_message'){

                $this->send_message($connection,$data);

            }

        };

        public function send_message($connection,$data){

            global $text_worker;

            if(isset($data['to_uid'])){

            var_dump($data['to_uid']);

            if(isset($text_worker->uidConnections["{$data['to_uid']}"])){

                $to_connection=$text_worker->uidConnections["{$data['to_uid']}"];

                $to_connection->send($data['uid'].$data['message']);

            }

        }

    }



五、服务器向浏览器通信

1. workeman 监听一个本地发送的端口,在启动的时候

//当启动workerman的时候 触发此方法

        $text_worker->onWorkerStart =function(){

            //监听一个内部端口,用来接收服务器的消息,转发给浏览器

            $inner_text_worker = new Worker('Text://127.0.0.1:5678');

            $inner_text_worker->onMessage = function($connection_admin, $data)

            {

                global $text_worker;

                // $data数组格式,里面有uid,表示向那个uid的页面推送数据

                $data = json_decode($data, true);

                var_dump($data);

                $to_uid = $data['to_uid'];

                var_dump($to_uid);

                // 通过workerman,向uid的页面推送数据

                // $ret = sendMessageByUid($uid, $buffer);

                $connection = $text_worker->uidConnections[$to_uid];

                $connection->send($data);

                // 返回推送结果

                $connection_admin->send(true ? 'ok' : 'fail');

            };

            $inner_text_worker->listen();

        };

//控制器代码

class TestController extends Controller

{

    public function send(){

        $client = stream_socket_client('tcp://127.0.0.1:5678', $errno, $errmsg, 1);

        // 推送的数据,包含用户,表示是给这个用户推送

        $data = array (‘uid’=>37,’group’=>’admin’, ‘message’=>’发送成功啦’, ‘to_uid’=>36); 

        // 发送数据,注意5678端口是Text协议的端口,Text协议需要在数据末尾加上换行符

        fwrite($client, json_encode($data)."\n");

}

}


————————————————

原文作者:Wall_E

转自链接:https://learnku.com/articles/56624

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。


有话要说