在 Laravel 中使用 基於Workerman 的Gateway-worker進行 socket 長連接通訊

1、安裝gateway-worker

gateway-worker 它已經引入了 workerman/workerman.

composer require workerman/gateway-worker
composer require workerman/gatewayclient

如果找不到此包,建議更換composer源。阿里的源找不到,我重置到官方源可以安裝。源連接

它們兩個接口很多是類似的。

2. 創建 Workerman 啓動文件

創建一個 artisan 命令行工具來啓動 Socket 服務端,在 app/Console/Commands 目錄下建立命令行文件。

php artisan make:command GatewayWorkerServer

 

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use GatewayWorker\BusinessWorker;
use GatewayWorker\Gateway;
use GatewayWorker\Register;
use Workerman\Worker;


class GatewayWorkerServer extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'workman {action} {--d}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Start a Workerman server.';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        //
        global $argv;
        $action = $this->argument('action');

        $argv[0] = 'artisan workman';
        $argv[1] = $action;
        $argv[2] = $this->option('d') ? '-d' : '';   //必須是一個-,上面定義命令兩個--,後臺啓動用兩個--

        $this->start();
    }

    private function start()
    {
        $this->startGateWay();
        $this->startBusinessWorker();
        $this->startRegister();
        Worker::runAll();
    }

    private function startBusinessWorker()
    {
        $worker                  = new BusinessWorker();
        $worker->name            = 'BusinessWorker';
        $worker->count           = 1;
        $worker->registerAddress = '127.0.0.1:1236';
        $worker->eventHandler    = \App\GatewayWorker\Events::class;
    }

    private function startGateWay()
    {
        $gateway = new Gateway("websocket://0.0.0.0:2346");
        $gateway->name                 = 'Gateway';
        $gateway->count                = 1;
        $gateway->lanIp                = '127.0.0.1';
        $gateway->startPort            = 2300;
        $gateway->pingInterval         = 30;
        $gateway->pingNotResponseLimit = 0;
        $gateway->pingData             = '{"type":"ping"}';
        $gateway->registerAddress      = '127.0.0.1:1236';
    }

    private function startRegister()
    {
        new Register('text://0.0.0.0:1236');
    }

       //php artisan workman start --d  之後    打開瀏覽器F12 將內容複製到console裏return就行
       /* ws = new WebSocket("ws://192.168.136.128:2346");
        ws.onopen = function() {
            ws . send('{"name":"one","user_id":"111"}');
            ws . send('{"name":"two","user_id":"222"}');
        };
        ws.onmessage = function(e) {
            console.log("收到服務端的消息:" + e.data);
        };
        ws.onclose = function(e) {
            console.log("服務已斷開" );
        };*/

}

3. 創建事件監聽文件

創建一個 app/GatewayWorker/Events.php 文件來監聽處理 workman 的各種事件。

 

 

<?php
/**
 * Created by PhpStorm.
 * User: ls
 * Date: 2020/3/25
 * Time: 16:09
 */
namespace App\GatewayWorker;

use GatewayWorker\Lib\Gateway;
use Illuminate\Support\Facades\Log;

class Events
{

    public static function onWorkerStart($businessWorker)
    {
        echo "onWorkerStart\r\n";
    }

    public static function onConnect($client_id)
    {
        Gateway::sendToClient($client_id, json_encode(['type' => 'onConnect', 'client_id' => $client_id]));
        echo "onConnect\r\n";
    }

    public static function onWebSocketConnect($client_id, $data)
    {
        echo "onWebSocketConnect\r\n";
    }

    public static function onMessage($client_id, $message)
    {
        Gateway::sendToClient($client_id, json_encode(['type' => 'onMessage', 'client_id' => $client_id, 'name' => json_decode($message)->name]));

        echo "onMessage\r\n";
    }

    public static function onClose($client_id)
    {
        Log::info('Workerman close connection' . $client_id);
        echo "onClose\r\n";
    }

}

4、測試。 啓動 Workerman 服務端

在命令行裏面執行,支持的命令大概有 start|stop|restart,其中 --d 的意思是 daemon 模式,後臺守護進程。

php artisan workman start --d
ls@ls-virtual-machine:/var/www/html/socket/socket$ php artisan workman start --d
Workerman[artisan workman] start in DAEMON mode
-------------------------------------------- WORKERMAN ---------------------------------------------
Workerman version:4.0.2          PHP version:7.2.24-0ubuntu0.18.04.3
--------------------------------------------- WORKERS ----------------------------------------------
proto   user            worker            listen                      processes    status           
tcp     ls              Gateway           websocket://0.0.0.0:2346    1             [OK]            
tcp     ls              BusinessWorker    none                        1             [OK]            
tcp     ls              Register          text://0.0.0.0:1236         1             [OK]            
----------------------------------------------------------------------------------------------------
Input "php artisan workman stop" to stop. Start success.

 在瀏覽器 F12 打開調試模式,在 Console 裏輸入

ws = new WebSocket("ws://192.168.136.128:2346");
    ws.onopen = function() {
        ws . send('{"name":"one","user_id":"111"}');
        ws . send('{"name":"two","user_id":"222"}');
    };
    ws.onmessage = function(e) {
        console.log("收到服務端的消息:" + e.data);
    };
    ws.onclose = function(e) {
        console.log("服務已斷開" );
    }

 

OK!

 

如果需要在控制器裏手動發送消息?

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use GatewayClient\Gateway;
use Illuminate\Support\Facades\Log;

class H5ssController extends Controller
{

    public function __construct()
    {
        // 設置GatewayWorker服務的Register服務ip和端口,請根據實際情況改成實際值(ip不能是0.0.0.0)
        Gateway::$registerAddress = '127.0.0.1:1236';

    }

    public static function sendMessage(Request $request)
    {

        $data = $request->json()->all();
        $message = json_encode($data);
        Gateway::sendToAll($message); //給所有客戶端發消息
        Gateway::sendToClient($client_id, $data);
        Gateway::sendToUid($uid, $message);// 向任意uid的網站頁面發送數據 
    }
Gateway::sendToAll($data);
Gateway::sendToClient($client_id, $data);
Gateway::closeClient($client_id);
Gateway::isOnline($client_id);
Gateway::bindUid($client_id, $uid);
Gateway::isUidOnline($uid);
Gateway::getClientIdByUid($uid);
Gateway::unbindUid($client_id, $uid);
Gateway::sendToUid($uid, $data);
Gateway::joinGroup($client_id, $group);
Gateway::sendToGroup($group, $data);
Gateway::leaveGroup($client_id, $group);
Gateway::getClientCountByGroup($group);
Gateway::getClientSessionsByGroup($group);
Gateway::getAllClientCount();
Gateway::getAllClientSessions();
Gateway::setSession($client_id, $session);
Gateway::updateSession($client_id, $session);
Gateway::getSession($client_id);

參考1    參考2 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章