用thinkphp6框架的think-swoole实现websocket的onRequest回调事件

为什么要写这个onRequest回调
1.用户链接socket后发送消息触发对应消息相应并回复 satisfy
2.用户链接socket后 我们在后台主动触发按钮调用接口去主动发送给指定用户 no satisfy
so,我们修改以下代码.

1.修改thinkphp6的底层类vendor/topthink/think-swoole/src/concerns/InteractsWithHttp.php第96行
    /**
     * "onRequest" listener.
     *
     * @param Request $req
     * @param Response $res
     */
    public function onRequest($req, $res)
    {
        /**
         * TinyMeng update start
         */
        $httpRequest = config("swoole.websocket.httpRequest");
        if(!empty($httpRequest)){
            if(isset($req->get['websocket'])){
                $websocket = new $httpRequest($this->getServer());
                return $websocket->onRequest($req,$res);
            }else{
                //return true;
            }
        }
        /** Tinymeng end */

        $args = func_get_args();
        $this->runInSandbox(function (Http $http, Event $event, App $app, Middleware $middleware) use ($args, $req, $res) {
            $event->trigger('swoole.request', $args);

            //兼容var-dumper
            if (class_exists(VarDumper::class)) {
                $middleware->add(ResetVarDumper::class);
            }

            $request = $this->prepareRequest($req);
            try {
                $response = $this->handleRequest($http, $request);
            } catch (Throwable $e) {
                $response = $this->app
                    ->make(Handle::class)
                    ->render($request, $e);
            }

            $this->sendResponse($res, $response, $app->cookie);
        });
    }
2.修改配置文件 config\swoole.php
<?php

use app\common\service\swoole\WebsocketMessage;
use app\common\service\swoole\SocketHandler;
use think\swoole\websocket\socketio\Parser;

return [
    'server'     => [
        'host'      => env('SWOOLE_HOST', '127.0.0.1'), // 监听地址127.0.0.1
        'port'      => env('SWOOLE_PORT', 9502), // 监听端口
        'mode'      => SWOOLE_PROCESS, // 运行模式 默认为SWOOLE_PROCESS
        'sock_type' => SWOOLE_SOCK_TCP, // sock type 默认为SWOOLE_SOCK_TCP
        'options'   => [
            'pid_file'              => runtime_path() . 'swoole.pid',
            'log_file'              => runtime_path() . 'swoole.log',
            'daemonize'             => true,//守护进程方式运行
            // Normally this value should be 1~4 times larger according to your cpu cores.
            'reactor_num'           => swoole_cpu_num(),
            'worker_num'            => swoole_cpu_num(),
            'task_worker_num'       => swoole_cpu_num(),
            'enable_static_handler' => true,
            'document_root'         => root_path('public'),
            'package_max_length'    => 20 * 1024 * 1024,
            'buffer_output_size'    => 10 * 1024 * 1024,
            'socket_buffer_size'    => 128 * 1024 * 1024,
        ],
    ],
    'websocket'  => [
        'enable'        => true,
        'handler'       => SocketHandler::class,//SocketHandler
        'httpRequest'   => WebsocketMessage::class,//监听onRequest回调
        'parser'        => Parser::class,
        'ping_interval' => 25000,
        'ping_timeout'  => 60000,
        'room'          => [],
        'listen'        => [],
        'subscribe'     => [],
    ],
    //热更新
    'hot_update' => [
        'enable'  => env('APP_DEBUG', false),
        'name'    => ['*.php'],
        'include' => [app_path(),config_path()],
        'exclude' => [],
    ],
];
3.监听用户SocketHandler触发 app\common\service\swoole\SocketHandler
<?php
namespace app\common\service\swoole;

use Swoole\Server;
use think\Config;
use think\Request;
use Swoole\Websocket\Frame;
use app\common\service\CommonService;
use think\swoole\contract\websocket\HandlerInterface;

class SocketHandler implements HandlerInterface
{
    /** @var Websocket */
    protected $websocket;
    /** @var Config */
    protected $config;

    /**
     * SocketHandler constructor.
     * @Author: TinyMeng <666@majiameng.com>
     * @param \Swoole\Server $server
     * @param Config $config
     */
    public function __construct(Server $server, Config $config)
    {
        $this->config = $config;
    }

    /**
     * 监听用户连接事件
     * @Author: TinyMeng <666@majiameng.com>
     * @param int     $fd
     * @param Request $request
     */
    public function onOpen($fd, Request $request){
        CommonService::writeLog("fd:".$fd."连接");
    }


    /**
     * 监听用户断开事件
     * @Author: TinyMeng <666@majiameng.com>
     * @param int $fd
     * @param int $reactorId
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function onClose($fd, $reactorId){
        CommonService::writeLog("fd:".$fd."断开");
        return true;
    }


    /**
     * 监听用户message事件
     * @Author: TinyMeng <666@majiameng.com>
     * @param Frame $frame
     * @return bool
     */
    public function onMessage(Frame $frame){
        $packet = trim($frame->data);
        CommonService::writeLog("onMessage:".$packet.".");
        return true;
    }

}

4.监听onRequest回调,程序主动触发给用户 app\common\service\swoole\WebsocketMessage

<?php
namespace app\common\service\swoole;
use Swoole\Websocket\Frame;
use Swoole\WebSocket\Server;

class WebsocketMessage extends Websocket
{
    /**
     * \Swoole\Server
     * @Author: TinyMeng <666@majiameng.com>
     * Websocket constructor.
     * @param Server $server
     */
    public function __construct(Server $server)
    {
        parent::__construct($server);
    }

    /**
     * onRequest回调
     * //127.0.0.1:9502/?websocket=1&action=ONLINEADD&packet=
     * @Author: TinyMeng <666@majiameng.com>
     * @param $req
     * @param $respone
     */
    public function onRequest($req, $respone){
        if (!empty($req->get['packet'])) {
            CommonService::writeLog("onRequest:".$req->get['packet'].".");
        }

        $respone->end("success");
    }
}

5.主动触发发送

use tinymeng\tools\HttpRequest;

        try{
            $url = "//127.0.0.1:9502/";
            $packet_array = [
                'websocket'=>1,
                'trigger'=>1,
                'packet'=>json_encode($data),//发送的消息内容
            ];
            HttpRequest::httpGet($url,$packet_array);
        }catch (\Exception $exception){
            ExceptionHandle::sendErrorEmail($exception);
            return false;
        }
Last modification:October 29th, 2020 at 09:58 am
如果觉得我的文章对你有用,请随意赞赏