laravel使用workerman 使用者互動、伺服器互動

Wall_E發表於2021-04-24

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}] 建立成功");
    }

這時候瀏覽器就會出現列印資訊

laravel使用workerman 使用者互動、伺服器互動

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']);
            }
        }
    }

laravel使用workerman 使用者互動、伺服器互動

五、伺服器向瀏覽器通訊

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");
}
}

laravel使用workerman 使用者互動、伺服器互動

結語

有不足之處,請大家指正!謝謝!

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章