tp6 think-swoole4.0 websocket 使用的坑

我使用时的环境

Centos 7.9
PHP 7.4
Swoole	4.8.5
thinkPHP6 6.0.8
think-swoole 4.0

问题描述:socket.io与服务器连接成功,但是服务器没有根据客户端发的请求去执行,没有任何的返回,根本就没执行到listen中写的行为

网上的例子找了不少,其实网上也没几个,都试了一下,代码基本都是大同小异,但是我试的时候就是跑不起来,只要在config/swoole.php配置文件中开启了websocket,连接是成功的,但是就是没有返回,直到看到了这篇文章【think-swoole4.0.4 websocket 使用(追梦人)】,照着里面的例子,客户端终于能接收到数据了。我寻思着这是为啥呢?他的config/swoole.php中listen中的配置如下。
在这里插入图片描述
于是我照葫芦画瓢也复制了一条例子,在他下面新加了一条记录,结果又是不行?这我就emo了呀。加了交流群,但是没人鸟我,没办法了,只能翻他的源码了,一路从入口文件往下翻,终于在代码中发现了原因。在源码中只触发了swoole.websocket.Event的监听行为

文件位置:vendor/topthink/think-swoole/src/websocket/socketio/Handler.php

在这里插入图片描述
在他的源码中,当触发了onMessage事件时,它只触发了’swoole.websocket.Event’事件(这个事件名称为什么长成这样,跟config/swoole.php中不一样,是因为他在建立构建websocket服务的时候,会把在config/swoole.php中listen中写的参数转换成这样的形式。因为这个行为是依靠tp6中event来实现的,所以也可以直接在app/event.php中直接按照这样的形式写),不懂他为什么不写成通用的方式,现在这样写的话,,看他传入了$type(方法名),$data(客户端传递的参数)这些数据,就是说其实利用的就只是那一个监听行为,你自己在app\listener\WebsocketEvent.php中handler函数中去根据$type去判断要执行那个方法喽。只有一个监听行为,是不是可以不卡一些,然后运行的快一点??

我尝试着把此处的代码改成了这样,只要改成这样网上哪些例子就都能跑了,这样在config/swoole.php中配置的listen中填的那些行为。在客户端中触发哪个就走那个。

$result = $this->event->trigger('swoole.websocket.'.Str::studly($type), new WsEvent($type, $data));

不过我不建议这么改,因为我也不懂为什么不这样写,但是他现在的写法一定有道理,还是按他的来吧。而且改插件源码什么的,不合适!

代码

config\swoole.php
<?php

use think\swoole\websocket\socketio\Handler;

return [
    'http'       => [
        'enable'     => true,
        'host'       => '0.0.0.0',
        'port'       => 8998,
        'worker_num' => swoole_cpu_num(),
        'options'    => [],
    ],
    'websocket'  => [
        'enable'        => true,
        'handler'       => Handler::class,
        'ping_interval' => 25000,
        'ping_timeout'  => 60000,
        'room'          => [
            'type'  => 'table',
            'table' => [
                'room_rows'   => 8192,
                'room_size'   => 2048,
                'client_rows' => 4096,
                'client_size' => 2048,
            ],
            'redis' => [
                'host'          => '127.0.0.1',
                'port'          => 6379,
                'max_active'    => 3,
                'max_wait_time' => 5,
            ],
        ],
        'listen'        => [
			'event' => \app\listener\WebsocketEvent::class,
			'test' => \app\listener\WebsocketTest::class
	],
        'subscribe'     => [],
    ],
    'rpc'        => [
        'server' => [
            'enable'     => false,
            'host'       => '0.0.0.0',
            'port'       => 9000,
            'worker_num' => swoole_cpu_num(),
            'services'   => [],
        ],
        'client' => [],
    ],
    //队列
    'queue'      => [
        'enable'  => false,
        'workers' => [],
    ],
    'hot_update' => [
        'enable'  => env('APP_DEBUG', false),
        'name'    => ['*.php'],
        'include' => [app_path()],
        'exclude' => [],
    ],
    //连接池
    'pool'       => [
        'db'    => [
            'enable'        => true,
            'max_active'    => 3,
            'max_wait_time' => 5,
        ],
        'cache' => [
            'enable'        => true,
            'max_active'    => 3,
            'max_wait_time' => 5,
        ],
        //自定义连接池
    ],
    'tables'     => [],
    //每个worker里需要预加载以共用的实例
    'concretes'  => [],
    //重置器
    'resetters'  => [],
    //每次请求前需要清空的实例
    'instances'  => [],
    //每次请求前需要重新执行的服务
    'services'   => [],
];

app\listener\WebsocketEvent.php
<?php
declare (strict_types = 1);

namespace app\listener;
use think\Container;
use think\swoole\Websocket;
class WebsocketEvent
{
    public $websocket = null;

    public function __construct(Container $container) {
        $this->websocket = $container->make(Websocket::class);
    }
    /**
     * 事件监听处理
     *
     * @return mixed
     */
    public function handle($event)
    {
        echo "Event\n";
        $func = $event->type; // 要调用的方法
        if (!method_exists($this, $func)) {
           $this->websocket->emit('testcallback', ['msg'=> $func.':方法不存在']);
        } else {
           $this->$func($event);
        }
    }


    /**
     * 测试类型
     * @param $event
     */
    public function test($event)
    {
        $this->websocket->emit('testcallback', ['aaaaa' => 1, 'getdata' => '123123']);
    }
}
~      
app\listener\WebsocketTest.php
<?php
declare (strict_types = 1);

namespace app\listener;
use think\Container;
use think\swoole\Websocket;
class WebsocketTest
{
    public $websocket = null;

    public function __construct(Container $container) {
        $this->websocket = $container->make(Websocket::class);
    }

    /**
     * 事件监听处理
     *
     * @return mixed
     */
    public function handle($event)
    {
       $this->websocket->emit("testcallback", ['msg'=> '来自listen-test的数据返回']);
    }
}

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.socket.io/socket.io-1.4.4.js"></script>
    <script src="https://code.jquery.com/jquery-1.11.1.js"></script>
</head>
<body>

<div>
    <div>
        返回内容:
    </div>
    <div style="width: 600px;height: 600px" id="content">

    </div>
</div>
<div>
    在控制台中执行 socket.emit("test",{"asd":"我是内容"})
</div>
<div>
    在控制台中执行 socket.emit("join",{"room":"roomtest"})  加入房间
</div>
<div>
    在控制台中执行 socket.emit("leave",{"room":["roomtest"]})  离开房间
</div>
<script>

    var  socket = io('http://0.0.0.0:8998',{transports: ['websocket']});
    //xxx.com 这个自己替换成自己的环境thinkphp-swoole 的端口或者是nginx的代理端口
    //transports: ['websocket'] 一定要这个,改为websocket链接
    //polling 这个不支持,轮询会导致请求变成http请求,post请求全部拒接掉
    socket.emit('test',{"asd":"asd"});
    //自定义msg事件,发送‘你好服务器’字符串向服务器
    socket.on('testcallback',(data)=>{
        //监听浏览器通过msg事件发送的信息
        console.log('服务器返回的数据:', data);//你好浏览器
    });
    socket.emit('join',{"asd":"asd"});
    socket.on('roomJoin',(data)=>{
        console.log(data);//你好浏览器
    })
</script>
</body>
</html>

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
think-swoole 是一个基于 Swoole 扩展的 PHP 框架,它提供了对 WebSocket 的支持。下面是一个简单的示例: ```php // 定义 WebSocket 控制器类 namespace app\index\controller; use think\swoole\WebSocket; class Chat extends WebSocket { protected $server; // WebSocket 连接建立时触发的事件 public function onOpen($server, $request) { $this->server = $server; $this->send($request->fd, 'Welcome to Chat Room!'); } // WebSocket 接收到消息时触发的事件 public function onMessage($server, $frame) { $data = $frame->data; foreach ($server->connections as $fd) { $this->send($fd, $data); } } // WebSocket 连接关闭时触发的事件 public function onClose($server, $fd) { echo "client-{$fd} is closed\n"; } } ``` 在上面的代码中,我们定义了一个名为 Chat 的 WebSocket 控制器类,它继承了 think\swoole\WebSocket 类,并实现了三个事件方法 onOpen、onMessage 和 onClose。在 onOpen 方法中,我们向客户端发送了一条欢迎信息;在 onMessage 方法中,我们将接收到的消息发送给所有连接的客户端;在 onClose 方法中,我们输出了客户端关闭的信息。 接下来,在路由配置文件中定义 WebSocket 路由: ```php // 定义 WebSocket 路由 use think\facade\Route; Route::get('/ws', 'index/Chat'); ``` 最后,在 Swoole 服务器配置文件中开启 WebSocket 服务: ```php // Swoole 服务器配置文件 use think\swoole\Server; return [ 'host' => '0.0.0.0', 'port' => 9501, 'type' => Server::SERVER_TYPE_WEB_SOCKET, 'mode' => SWOOLE_PROCESS, 'sock_type' => SWOOLE_SOCK_TCP, 'option' => [ 'worker_num' => 8, 'daemonize' => false, 'backlog' => 128, ], ]; ``` 在上面的代码中,我们将服务器的类型设置为 WebSocket,并开启了 8 个 Worker 进程。 现在,我们就可以启动 Swoole 服务器,并在客户端连接到 WebSocket 服务后进行消息的发送和接收了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值