在 Laravel 中使用 Workerman 进行 socket 通讯
47

1.安装 Workerman

由于要使用客户端点对点通讯,选择了 workerman/gateway-worker 的扩展包,它已经引入了 workerman/workerman

$ composer require workerman/gateway-worker

2.创建 Workerman 启动文件

创建一个 artisan 命令行工具来启动 Socket 服务端,在 app/Console/Commands 目录下建立命令行文件。

<?php

namespace App\Console\Commands;

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

class WorkermanCommand extends Command
{

    protected $signature = 'workman {action} {--d}';

    protected $description = 'Start a Workerman server.';

    public function handle()
    {
        global $argv;
        $action = $this->argument('action');

        $argv[0] = 'wk';
        $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\Workerman\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":"@heart@"}';
        $gateway->registerAddress      = '127.0.0.1:1236';
    }

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

3.创建事件监听文件

创建一个 app/Workerman/Events.php 文件来监听处理 workman 的各种事件。

<?php

namespace App\Workerman;

class Events
{

    public static function onWorkerStart($businessWorker)
    {
    }

    public static function onConnect($client_id)
    {
    }

    public static function onWebSocketConnect($client_id, $data)
    {
    }

    public static function onMessage($client_id, $message)
    {
    }

    public static function onClose($client_id)
    {
    }
}

4.启动 Workerman 服务端

在命令行里面执行,支持的命令大概有 start|stop|restart,其中 -d 的意思是 daemon 模式。

$ php artisan workman start -d

当你看到如下结果的时候,workman已经启动成功了。

Workerman[wk] start in DEBUG mode
----------------------- WORKERMAN -----------------------------
Workerman version:3.5.11          PHP version:7.1.11
------------------------ WORKERS -------------------------------
user          worker          listen                    processes status
root          Gateway         websocket://0.0.0.0:2346   1         [OK]
root          BusinessWorker  none                       1         [OK]
root          Register        text://0.0.0.0:1236        1         [OK]
----------------------------------------------------------------
Press Ctrl+C to stop. Start success.
onWorkerStart

表述能力不是很好,按照这个流程,可以很快的搭建起基于 workerman 的 socket 服务端,其中的运行配置参数等,大家自行百度吧。

本帖由系统于 2个月前 自动加精
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 15
tegic

Waring: App\Workerman\Events::onMessage is not callable

4个月前
tegic

解决了,events引用错了

4个月前

集成进来以后能在 workerman 的各种事件里适用 laravel ORM 吗? 貌似不行.

4个月前

@overfalse 可以使用的啊

4个月前

@overfalse

    public static function onWebSocketConnect($client_id, $data)
    {
        echo "onWebSocketConnect\r\n";
        Auth::guard('api')->setToken($data['server']['HTTP_AUTHORIZATION']);
        Gateway::bindUid($client_id, Auth::guard('api')->id());
        Gateway::joinGroup($client_id, $data['server']['HTTP_ROOMID']);
    }
4个月前

@小陈叔叔 我集成 Workerman , 然后在 Workerman 的回调里面适用 orm, 前几分钟可以, 再久一点就不行了, 应该是生命周期问题. 不知道你这里有没解决方案.

4个月前
tegic

@overfalse GatewayWorker最好不处理任何业务逻辑,如果你需要服务端向客户端推送数据的话可以用Gateway的API(GatewayClient),这样你就可以在controller调用api就行。

4个月前

@overfalse 这个还真没试过,只是集成了有些东西还没来的急去重构,如果数据库断开的话,你可以看一下数据库的重连机制,或者是使用长连接

4个月前

很不错!

4个月前

不错的整合文章,谢谢分享。

2个月前

@小陈叔叔 你是不是少了一条用php artisan创建文件的命令了啊?

2个月前

@overfalse 你需要断线重连机制。

2个月前

做完啊,stop,reload, -d

2个月前
sheldon
1个月前

@HectorChan 自动创建和手动创建的结果都是一样的 主要是这个思路

1个月前

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!