thinkphp6+swoole websocket自研路线

对于think-swoole网上资料五花八门,根据网上资料,我成功走上了岔路口,但是websocket连接时也可以走通,因为项目比较急,既然能走通那就直接用,也做成了满足需求的聊天软件,但是本着质量至上的态度,我又把代码改了一份正规的路线,下面分享我的 websocket自研路线 ,紧分享学习路程,不建议使用,正规路线在最下方。

安装think-swoole

ThinkPHP 6 安装命令

具体操作

config/swoole.php

复制一份think\swoole\websocket\socketio\Handler.php到app\http\Ywliveanchor.php

app\http\Ywliveanchor.php

<?php

namespace app\http;

use Swoole\Server;
use Swoole\Websocket\Frame;
use Swoole\WebSocket\Server as WebsocketServer;
use think\Config;
use think\Request;
use think\swoole\contract\websocket\HandlerInterface;

class Ywliveanchor implements HandlerInterface
{
    /** @var WebsocketServer */
    protected $server;

    /** @var Config */
    protected $config;

    public function __construct(Server $server, Config $config)
    {
        $this->server = $server;
        $this->config = $config;
    }

    /**
     * "onOpen" listener.
     *
     * @param int     $fd
     * @param Request $request
     */
    public function onOpen($fd, Request $request)
    {
        echo "队列{$fd}连接\n";
    }

    /**
     * "onMessage" listener.
     *  only triggered when event handler not found
     *
     * @param Frame $frame
     * @return bool
     */
    public function onMessage(Frame $frame)
    {
        $packet = $frame->data;
        if (Packet::getPayload($packet)) {
            return false;
        }

        $this->checkHeartbeat($frame->fd, $packet);

        return true;
    }

    /**
     * "onClose" listener.
     *
     * @param int $fd
     * @param int $reactorId
     */
    public function onClose($fd, $reactorId)
    {
        return;
    }

    protected function checkHeartbeat($fd, $packet)
    {
        $packetLength = strlen($packet);
        $payload      = '';

        if ($isPing = Packet::isSocketType($packet, 'ping')) {
            $payload .= Packet::PONG;
        }

        if ($isPing && $packetLength > 1) {
            $payload .= substr($packet, 1, $packetLength - 1);
        }

        if ($isPing) {
            $this->server->push($fd, $payload);
        }
    }
}

标准的websocket连接方式使用原生swoole处理即可

逻辑完成后

php  think swoole

开启多服务时报错:swoole http server process is already running.

think\swoole\command\Server.php

注释掉

// if ($pidManager->isRunning()) {
        //     $this->output->writeln('<error>swoole http server process is already running.</error>');
        //     return;
        // }

示例逻辑

public function onMessage(Frame $frame)
    {
       \go(function ()use($frame) {
        $redis = new \Redis();
        $redis->connect('127.0.0.1', 6379);
        $data=json_decode($frame->data);
        // var_dump($data);
        // if($data->con=='not_logged_in'){
        //     //未登录
        //     //存储房间信息
        //     $redis->sAdd('room'.$data->roominfo->id,$frame->fd);
        //     $redis->set('fd_roominfo'.$frame->fd,json_encode($data->roominfo));
        // }else
        if($data->con=='already_logged_in'){
       	    // //已登录存储用户信息
       	    
       	    //1.提供user列表
            $redis->set('fd_userinfo'.$frame->fd,json_encode($data));//fd绑定info消息
       	    $redis->zAdd('user'.$data->roominfo->id,$frame->fd,json_encode($data));// 有序集合记录房间info列表信息
       	    $info=$redis->zRevRange('user'.$data->roominfo->id, 0, -1);//获取房间info列表信息
       	    
       	    //2.提供user单个信息
       	    // $redis->set('fd_userinfo'.$frame->fd,json_encode($data->userinfo));//fd绑定userinfo
            // $userinfo=$redis->get('fd_userinfo'.$frame->fd);
            
            
            //存储房间信息
            $redis->set('fd_roominfo'.$frame->fd,json_encode($data->roominfo));//fd绑定房间
            $redis->sAdd('room'.$data->roominfo->id,$frame->fd);//无序集合记录房间fd列表
            $room=$redis->sMembers('room'.$data->roominfo->id);//获取房间fd列表
            var_dump($room);
        	$res=array(
        			 'open'=>'1',
                     //'data'=>['con'=>'open','msg'=>'发送成功','count'=>count($room),'info'=>json_decode($userinfo)]
                     'data'=>['con'=>'open','msg'=>'发送成功','count'=>count($room),'info'=>$info]
            );
           
        }elseif($data->con=='already_logged_out'){
            $roominfo= json_decode($redis->get('fd_roominfo'.$frame->fd));//获取房间信息
            $redis->srem('room'.$roominfo->id,$frame->fd);//删除房间信息
            $room=$redis->sMembers('room'.$roominfo->id); //获取房间fd列表
            var_dump($room);
            //1.提供user列表
            $data=$redis->get('fd_userinfo'.$frame->fd);//获取关闭用户的info信息
            // var_dump($data);
            $a=$redis->zRem('user'.$roominfo->id,$data);
            // var_dump($a);
            $info=$redis->zRevRange('user'.$roominfo->id, 0, -1);
            $redis->del('fd_userinfo'.$frame->fd);//移除房间用户
       	    // var_dump($info);
       	    
       	    //2.提供user单个信息
            // $userinfo=$redis->get('fd_userinfo'.$frame->fd);
            // $redis->del('fd_userinfo'.$frame->fd);
            $res=array(
        	   'open'=>'1',
               //'data'=>['con'=>'close',"count"=>count($room),'info'=>json_decode($userinfo)]
               'data'=>['con'=>'close','msg'=>'发送成功','count'=>count($room),'info'=>$info]
            );
            echo "队列{$frame->fd}关闭1\n";
        }
        \go(function ()use($res,$room) {
         $jsonStr = json_encode($res);
            foreach($room as $fd){
                $this->server->push($fd, $jsonStr); 
          }
        });
    }

正规方式

0 评论
内联反馈
查看所有评论