swooletw / laravel-swoole 怎么主动推送消息

有大佬使用过 swooletw/laravel-swoole 这个包吗,我想咨询一下,我怎么在知道 fd 的情况下,在外部随意找个地方主动给这个 fd 推送一个消息过去呢
App::make (Server::class)->push ($fd, $payload); 我尝试着用这种,也一直报错。

如果是前端连接我的 websocket 服务器进行消息互通是可以的,

现在我有个需求就是,主动向现在正链接着的所有 fd 的其中一个推送一个消息,我使用的方式是

如果用网页直接去跑这个代码就会报错需要使用 cli 模式,如下:

所以我就换成了用命令行模式,然后就继续报了另外一个错如下:

有大佬知道吗,还是我的做法本身就是错的,请稍加指点,感谢

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 17

贴下你的报错

3年前 评论
xh_dream (楼主) 3年前
哪吒的狗腿子 (作者) 3年前

我的理解是,可以针对上下线去缓存 fd,离线删除 fd,然后就可以针对在线的用户推送消息了。

最后一图的异常提示 98 端口已经被占用了,先 ps -ef 查看是什么进程占用了,非系统进程的话直接 kill 掉再重启;如果是系统进程的话,改完 websocket 端口后再启动,再往下走。

3年前 评论
xh_dream (楼主) 3年前

你下面的报错是端口已被使用了,或者说你已经启动了,然后你正在尝试又一次开启服务。你可以杀掉对应进程重新启动

3年前 评论
xh_dream (楼主) 3年前

有两种实现方案。

方案一

在 websocket 服务端,多监听一个 http 端口,接收来自于后台管理员的 http 推送请求,然后调用 ws 句柄进行推送。

方案二

后台管理代码封装好一个 websocket 协议的推送方法,推送参数中添加一个管理员标识参数,当 websocket 服务端服务端接收到 ws 消息的时候,通过管理员标识,即可知道该消息是做什么用的,接下来就可以做 群体推送的代码逻辑。

3年前 评论
xh_dream (楼主) 3年前

你的做法是严重错误的, 你的 websocket 服务端,是常驻进程的另一个服务。

然而你想着通过你的 http 请求下的 PHP-FPM 工作模式,去直接调用 swoole 启动的类实例,是无法调用到的,即使你用 cli 调用也不行,因为这两个程序根本就不在同一个内存空间。

通俗的理解(不太准确),你可以把 websocket 服务代码,业务 api 代码,当成两个不同的项目,部署到了不同服务器。然后你琢磨,不同项目之间,通过直接调用静态类,能调用到吗?

3年前 评论
哪吒的狗腿子 3年前
kolin 3年前
xh_dream (楼主) 3年前

这个你要看你的前端运行的是 fpm 还是 swoole 提供的服务,如果是 fpm 模式,得连一个客户端转到 swoole,如果是 swoole 则可以直接发送。cli 命令行也得边接一个客户端
如我搞的就是自动判断走那一个:

try {
                //加入本句用于验证当前是否cli模式的http请求
                Websocket::getSender();
                $this->api = CliIm::instance();
            } catch (\Exception $exception) {
                //如果cli模式出现错误则转为普通fpm的http请求模式
                $this->api = FpmIm::instance();
            }

fpm 客户端连接参考

$port = config('swoole_http.server.port', '1215');
$this->client = new Client(['base_uri' => 'http://0.0.0.0:' . $port]);
$response = $this->client->request('POST', 'swoole/im/send', $data);

建一个内部的 swoole/im/send 接口接收直接处理了,因为 client 是 swoole 连接了
swoole 模式下:
Websocket::toUserId($uid)->emit($type, $content);
就直接用 websocket 下的 emit 方法发送消息

3年前 评论
xh_dream (楼主) 3年前

现场我的做法是从 fpm 推送消息到 swoole 的服务端,但是一直在路由 websocket.php 的 connect 事件中,一直走不到其他的事件路由,楼主走通了吗?

2年前 评论
xh_dream (楼主) 2年前