kucherenkoai/laravel-websockets-zmq

dev-master 2021-01-10 18:35 UTC

This package is auto-updated.

Last update: 2024-09-11 03:44:15 UTC


README

这是一个使用 ZMQ 和 Ratchet 库的 WebSocket 包。

使用 docker 安装 WebSocketsZMQ

php-fpm

RUN apt-get update -yqq && \
    apt-get install -y build-essential libtool autoconf pkg-config libsodium-dev libzmq3-dev && \
    curl -L -O  https://github.com/zeromq/php-zmq/archive/master.zip && \
    unzip master.zip && \
    cd php-zmq-master && phpize && ./configure && \
    make && \
    make install

并且需要在 php.ini 文件中添加 extension=zmq.so 行。

工作区

RUN apt-get update -yqq && \
    apt-get install -y build-essential libtool autoconf pkg-config libsodium-dev libzmq-dev && \
    git clone git://github.com/mkoppanen/php-zmq.git && \
    cd php-zmq && phpize && ./configure && \
    make && \
    make install

RUN apt-get update -yqq && \
    echo "extension=zmq.so" >> /etc/php/${LARADOCK_PHP_VERSION}/cli/php.ini

Laravel 后端

Composer

您需要运行 composer 终端命令

composer require kucherenkoai/laravel-websockets-zmq

config/app.php

在这个配置文件中,我们需要添加新的 WebSockets 提供者。

'providers' => [
    ...
    ...
    ...
    WebSocketsZMQ\Providers\WebSocketsZMQProvider::class <-- new row in providers side 
];

Composer 发布配置

php artisan vendor:publish --provider="WebSocketsZMQ\Providers\WebSocketsZMQProvider"

发布后,您将拥有一个新的配置文件 /config/zmqPusher.php,其中您可以更改 WebSocket 参数。此文件看起来像这样

<?php

return [
    'hosts' => [
        'server_host'       => '0.0.0.0:8080',
        'context_push_host' => '127.0.0.1:5555',
        'context_pull_host' => '127.0.0.1:5555',
    ],

    'logs' => [
        'connect'      => ['success' => true, 'error' => true],
        'user'         => ['success' => true, 'error' => true],
        'topic'        => ['success' => true, 'error' => true],
        'message'      => ['success' => true, 'error' => true],
        'request'      => ['success' => true, 'error' => true],
        'response'     => ['success' => true, 'error' => true],
        'notification' => ['success' => true, 'error' => true]
    ],

    'broadcast'       => 'App\Services\WebSockets\Broadcast\Broadcast',
    'router'          => 'App\Services\WebSockets\Router',
    'user_all_topics' => true,
];

并且您将拥有一个新的命令,该命令在所有配置完成后启动 WebSocket 服务器。此命令看起来像

php artisan command:webSocketServer   

config/logging.php

在此文件的通道部分需要添加新的日志通道以供 WebSocket 使用。

'channels' => [
    ...
    ...
    ...
    'webSocketsZMQ' => [
        'driver' => 'single',
        'path'   => storage_path('logs/web_sockets_zmq.log'),
        'level'  => 'debug',
    ],

];

用法

后端

为了使用库,需要创建 3 个文件

  1. Broadcast 文件。
  2. Route 文件。
  3. 自定义控制器(s) 文件(s)。

Broadcast 文件有 3 个方法

  1. connect 方法,其中允许或拒绝新用户登录。
  2. subscribe 方法,其中允许或禁止已经认证的用户连接到特定的主题。
  3. topics 方法,其中返回系统中可以监听的主题。

示例

<?php
namespace App\Services\WebSockets\Broadcast;

use App\Models\User;
use WebSocketsZMQ\Interfaces\Entities\BroadcastInterface;
use WebSocketsZMQ\Interfaces\Entities\UserInterface;
use WebSocketsZMQ\Entities\Broadcast as BaseBroadcast;

class Broadcast extends BaseBroadcast implements BroadcastInterface {

    protected function connect(array $connectionParams)
    {
        if(!$user = User::find($connectionParams['token'])){
            return null;
        }
        return $user->id;
    }

    protected function subscribe($topic, UserInterface $user): bool
    {
        if($topic == 'notifications' && $user->getId() == $user->getId()){
            return true;
        }
        return false;
    }

    public function topics(): array
    {
        return ['notifications'];
    }
}

Router 文件有 2 个方法

1. 方法检查哪个用户将消息发送到哪个路由 2. 完成我们将使用的路由

  1. auth 方法检查哪个用户将消息发送到哪个路由。如果用户有访问权限则返回 bool true,如果没有则返回 false。
  2. routes 添加路由(添加新路由时的参数:路由名称、自定义控制器文件、我们将使用的控制器方法)。

示例

<?php

namespace App\Services\WebSockets;

use App\Http\Requests\User\UserCreateRequest;
use App\Services\WebSockets\Controllers\Notification;
use WebSocketsZMQ\Interfaces\Entities\RouterInterface;
use WebSocketsZMQ\Interfaces\Entities\UserInterface;
use WebSocketsZMQ\Route\Router as BaseRouter;

class Router extends BaseRouter implements RouterInterface {

    public function auth($topic, UserInterface $user): bool
    {
        if($topic == 'notifications' && $user->getId() == $user->getId()){
            return true;
        }
        return false;
    }

    /**
     * If we can use request api validation we can add 4 param.
     *  $this->addRouter('notifications',Notification::class,'get',UserCreateRequest::class);
     */
    public function routes(): void
    {
        $this->addRouter('notifications',Notification::class,'get');
    }
}

自定义控制器

示例

<?php

namespace App\Services\WebSockets\Controllers;

use App\Http\Resources\UserResource;
use App\Models\User;
use WebSocketsZMQ\Interfaces\Request\RequestInterface;
use WebSocketsZMQ\Response;

class NotificationController {

    public function get(RequestInterface $request)
    {
        $users[]   = $request->getUser()->getId();
        $body      = $request->getBody();
        $routeName = $request->getRouteName();

        $user = User::find($request->getUser()->getId());
        $userResource = new UserResource($user);

        $response = new Response();
        $response->addTopicName('notifications')->addUsers($users)->addData($userResource)->send();
    }

}

注释

响应文件不仅可以使用自定义控制器,还可以在应用程序的不同地方使用。

客户端

    var conn = new WebSocket('ws://:8080?token=3');
    conn.onopen = function(e) {
        console.log("Connection established!");
    };

    conn.onmessage = function(e) {
        console.log(e.data);
    };

    setTimeout(function () {
        conn.send(JSON.stringify([3,'notifications',{"name":"Bob","email":"testname@testmail.net"}]));
    },3000)

许可

LaravelWebSocketsZmq 是开源软件,许可协议为 license