如何在使用 Laravel WebSockets 时通过 WebSocket 从客户端向服务器发送消息?

11

WebSocket可以进行双向通信:服务器可以向浏览器发送消息,浏览器(客户端)可以通过同一连接回复。

我正在使用以下工具在Laravel 6中实现聊天应用:

我已经让服务器触发事件并让客户端监听这些事件,如下所示:

  1. 安装Laravel WebSockets包。

composer require beyondcode/laravel-websockets

  1. 配置config/broadcasting.php
        'pusher' => [
            'driver' => 'pusher',
            'key' => xxx,
            'secret' => xxx,
            'app_id' => xxx,
            'options' => [
                'cluster' => xxx,
                'encrypted' => true,
                'useTLS' => true, 
                'host' => '127.0.0.1',
                'port' => 6001,
                'scheme' => 'https',
            ],
        ],
    ]
  1. 配置config/websockets.php
'apps' => [
        [
            'id' => xxx,
            'name' => xxx,
            'key' => xxx,
            'secret' => xxx,
            'enable_client_messages' => true,
            'enable_statistics' => true,
        ],
    ],
  1. 安装 Pusher 服务器。

composer require pusher/pusher-php-server "~3.0"

  1. .env 文件中将广播驱动程序设置为使用 pusher

BROADCAST_DRIVER=pusher

  1. 在客户端使用 laravel-echopusher-js
import Echo from "laravel-echo"

window.Pusher = require('pusher-js');

window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'your-pusher-key',
    wsHost: window.location.hostname,
    wsPort: 6001,
    disableStats: true,
});
  1. 启动WebSockets服务器。

php artisan websockets:serve

  1. 在服务端,使用实现了ShouldBroadcastNow类的事件类来触发事件。

event(new MyEventClass((object)$message));

一切正常。在步骤8中,我从服务器端触发事件。

请注意,我没有使用官方的Pusher服务器,而是利用了Pusher API实现和pusher-js,但将指向配置在步骤6中的本地Laravel WebSockets服务器。

请不要将与laravel-echo-serverSocket.IO Server混淆。我没有使用Socket.IO Server

现在,我想从客户端触发事件,因为WebSocket允许双向通信。如何在Laravel中使用Laravel Echo JavaScript PackageLaravel WebSockets PHP package实现呢?


请问您能否提供您正在使用的确切软件包的链接(Laravel Echo JavaScript Package、Laravel WebSockets和pusher-js)? - Rwd
Laravel WebSockets 的链接:https://docs.beyondco.de/laravel-websockets/ - O Connor
推送器JS NPM包链接:https://www.npmjs.com/package/pusher-js - O Connor
谢谢。由于某种原因,我认为你指的是完全不同的Laravel Echo程序包。 - Rwd
你有解决这个问题吗?因为我这里也遇到了同样的问题!!! - Siros Fakhri
显示剩余6条评论
4个回答

1

请参考这份文档:https://pusher.com/docs/channels/using_channels/events#triggering-client-events

根据 Pusher 的文档,使用以下内容初始化您的前端:

 this.echo = new Pusher('mykey', {
    wsHost: 'localhost',
    wsPort: 6001,
    forceTLS: false,
    disableStats: true,
    enabledTransports: ['ws', 'wss']
  });

使用此代码触发您的事件。
var channel = this.echo.subscribe("private-channel");
channel.bind("pusher:subscription_succeeded", () => {
var triggered = channel.trigger("client-someEventName", {
   your: "data",
 });
});

0

我可能不正确,但我不认为你可以使用他们的pusher-js包进行推送操作。这就是pusher-php-server composer包的作用。

可能有一个适用于此的node package,但是为什么要重新发明轮子呢?只需要使用axios或Vuex action来发布到您的路由之一以触发事件,然后让Echo接收响应即可。

您甚至不需要创建控制器,只需使用路由闭包并触发事件即可。Axios或Vuex都将返回Promise,因此您可以在组件或Vuex操作中等待响应。

如果您尝试实现不同类型的Broadcast驱动程序,例如RabbitMQ或Rachet等,则我可以理解,但它旨在成为某种循环回路,从js向端点发送请求,从PHP触发事件,让Pusher或WebSockets完成其工作,在js中接收广播回传。


这不是Websockets工作的方式。已经存在一个ws连接。为什么我要一遍又一遍地向后端发送POST请求? - Mike Aron

0

对于可能遇到此问题的所有人。

您无需使用echo,并应直接从Pusher实例化。

const my_pusher = new Pusher("APP_KEY", {
        cluster: 'mt1',
        wsHost: window.location.hostname,
        wsPort: 6001,
        forceTLS: false,
        disableStats: true,
    });

发送消息到服务器:

my_pusher.send_event('EVENT_NAME',{'ANYTHING':'YOU_WANT'})

你不会用这个去访问服务器,它只是客户端的。因此,你不能对数据进行任何验证或其他操作。 - Michael Andersen
通过这段代码,客户端可以向服务器发送任何事件。任何验证都可以在服务器端提供。 - Lessmore

0

在初始化Echo之后,您需要在前端中监听特定的频道。我将展示一些Vue代码,但请根据实际情况进行修改:

Vue文件

export default {
    methods: {
        sendCommand(command) {
            axios.post('/api/command', { 'command': command })
            .then((res) => {
                //
            })
        }
    },
    mounted() {
        Echo.channel('xxx')
        .listen('.weight-change', (e) => {
            this.weight = e.weight
        })
    }
}

在这里,您可以看到所有传入消息都被捕获在代码的监听部分,并且通过后端的API路由将新消息发送到Echo频道。如有需要,请告诉我需要澄清的事项。

2
这与我已经完成的第8步相同,使用 axios.post('/api/command'),您可以向服务器发出API调用以触发事件。因此,事件正在服务器端触发。我正在寻找在客户端触发事件的解决方案。当您在VueJs组件中调用 sendCommand(command) 方法并调用 axios.post() 时,并不意味着您在客户端触发了事件。 - O Connor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接