千家信息网

怎么用swoole + js + redis实现简易聊天室

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要介绍"怎么用swoole + js + redis实现简易聊天室",在日常操作中,相信很多人在怎么用swoole + js + redis实现简易聊天室问题上存在疑惑,小编查阅了各式资料,
千家信息网最后更新 2026年11月02日怎么用swoole + js + redis实现简易聊天室

这篇文章主要介绍"怎么用swoole + js + redis实现简易聊天室",在日常操作中,相信很多人在怎么用swoole + js + redis实现简易聊天室问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"怎么用swoole + js + redis实现简易聊天室"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

公司需要用到在线聊天功能,先写了个demo出来展示效果。

主要用到了swoole的websocket,task和redis的string,hash,set,zet等。

聊天室分为10个频道,可以切换频道,频道计数等。

目前还没做聊天内容的加密。

按需求,聊天内容可能会每个频道保留最近一百条,聊天加密的话考虑aes,也有可能不加。后续看情况了。

目前还没做异常处理。回头继续完善之后可能会再进行更新。

先上代码吧,有疑问可以留言交流。这里是html代码 可以自己引入jq地址。

        WebSocketTestPage    

服务端代码

  ['uid','gid'],        1       =>  ['new_room','old_room'],        2       =>  ['level','data','room_id','uid','name','head'],        4       =>  ['level','data','gid','uid','name','head'],    ];    public function __construct() {        if(!isset($this->redis)){            $this->redis = $this->_getRedis();            $this->redis->select(10);            $this->redis->flushDB();        }        $this->_resetChatNum();        if(!isset($this->ws)){            $this->ws = new swoole_websocket_server( HOST, PORT);            $this->ws->set(                [                    'worker_num'                => WORKER,                    'task_worker_num'          => TASK,                ]            );            $this->ws->on("open", [$this,"onOpen"]);            $this->ws->on("message", [$this,"onMessage"]);            $this->ws->on("close", [$this,"onClose"]);            $this->ws->on("task", [$this,"onTask"]);            $this->ws->on("finish", [$this,"onFinish"]);            $this->ws->start();        }    }    public function onOpen($ws, $request) {        $msg = array(            'msg_type' => 0,        );        $this->_pushSysNotice($request->fd);        $ws->push($request->fd, json_encode($msg));    }    private function _pushOldMsg($fd, $channel, $guild = false){        $m = $this->redis->lRange(CL . $channel,0,CL_MAX_SIZE);        $msg = [];        foreach($m as $v){            $msg[] = json_decode($v,true);        }        if(!empty($msg))            $this->ws->task(['fds'=>[$fd],'msg'=>$msg]);        $this->redis->lTrim(CL . $channel,0,CL_MAX_SIZE);        if($guild){            $g_m = $this->redis->lRange(GCL . $guild,0,CL_MAX_SIZE);            $g_msg = [];            foreach($g_m as $v){                $g_msg[] = json_decode($v,true);            }            if(!empty($g_msg))                $this->ws->task(['fds'=>[$fd],'msg'=>$g_msg]);            $this->redis->lTrim(GCL . $guild,0,CL_MAX_SIZE);        }    }    private function _pushSysNotice($fd){        $this->redis->select(0);        $keys = $this->redis->keys(SM . '*');        $msg = array(            'msg_type' => 3,        );        if(!empty($keys)){            foreach($keys as $v){                $s_msg = $this->redis->get($v);                $msg['data'] = $s_msg;                $this->ws->push($fd, json_encode($msg));            }        }        $this->redis->select(10);    }    public function onMessage($ws, $frame) {        $data = json_decode($frame->data,true);        $ret = [];        switch($data['msg_type']){            case 0://初始化                if($this->_checkParam($this->in_param[0], $data)){                    $ret = $this->_setConnectInfo($frame->fd, $data);                    if($data['gid'] > 0)                        $this->_pushOldMsg($frame->fd,$ret['room_id'],$data['gid']);                }else{                    $ret = ['msg_type'=>'no param'];                }                break;            case 1://切换频道                if($this->_checkParam($this->in_param[1], $data)){                    $ret = $this->_changeChannel($frame->fd, $data);                }else{                    $ret = ['msg_type'=>'no param'];                }                break;            case 2://聊天                if($this->_checkParam($this->in_param[2], $data)){                    $ret = $this->_pushChatInfo($frame->fd, $data);                }else{                    $ret = ['msg_type'=>'no param'];                }                break;            case 3:                break;            case 4://公会聊天                if($this->_checkParam($this->in_param[4], $data)){                    $ret = $this->_pushChatInfo($frame->fd, $data,true);                }else{                    $ret = ['msg_type'=>'no param'];                }                break;            default:                $ws->push($frame->fd, "error");                break;        }        echo "fd: {$frame->fd} Message: {$frame->data} \n";        if(!empty($ret)){            $ws->push($frame->fd, json_encode($ret));        }    }    public function onClose($ws, $fd) {        $this->_delChatInfo($fd, true);    }    public function onTask($ws, $taskId, $workerId, $data) {        foreach($data['fds'] as $v){            $this->ws->push($v,json_encode($data['msg']));        }        return $taskId;    }    public function onFinish($ws, $taskId, $data) {        echo "task-{$taskId} is end\n";    }    //初始化频道计数器    private function _resetChatNum(){        for($i = 1; $i <= CHANNEL_MAX_SIZE; $i++){            $this->redis->zAdd(CNL, 0, CR . $i);        }    }    //获取人数最少频道    private function _getSuggestRoomId(){        $chat_list = $this->redis->zRange(CNL,0,0);        $no = substr($chat_list[0],14);        if(empty($no) || (int)$no < 1 || (int)$no > CHANNEL_MAX_SIZE){            $no = mt_rand(1,CHANNEL_MAX_SIZE);        }        return (int)$no;    }    //连接时设置推荐频道    private function _setConnectInfo($fd, $data){        $channel = $this->_getSuggestRoomId();        $this->_setChannelInfo($fd,$channel);        $this->redis->hSet(CF.$fd, 'uid',$data['uid']);        $this->redis->hSet(CF.$fd, 'gid',$data['gid']);        if(!empty($data['gid'])){            $this->redis->sAdd(GR.$data['gid'], $fd);        }        return array(            'msg_type'      => 1,            'data'          => $channel,            'room_id'               => $channel,            'code'          => 0,            'fd'            => $fd,        );    }    //设置频道相关数据    private function _setChannelInfo($fd, $channel){        //存入fd        $this->redis->sAdd(CR . $channel,$fd);        //变更计数器        $this->redis->zIncrBy(CNL, 1, CR . $channel);        //存入用户频道信息        $this->redis->hSet(CF.$fd, 'channel',(int)$channel);    }    //校验字段    private function _checkParam($param, $data){        foreach($param as $v){            if(!isset($data[$v]))return false;        }        return true;    }    //切换频道    private function _changeChannel($fd, $data){        $this->_delChatInfo($fd);        $this->_setChannelInfo($fd,$data['new_room']);        $this->_pushOldMsg($fd,$data['new_room']);        return array(            'msg_type'      => 1,            'data'          => $data['new_room'],            'code'          => 1,        );    }    //关闭连接时清除相关内容    private function _delChatInfo($fd, $del = false){        $channel = $this->redis->hget(CF.$fd,'channel');        if(empty($channel)) return true;        $this->redis->sRem(CR .$channel, $fd);        if($del){            $this->redis->del(CF.$fd);        }        $this->redis->zIncrBy(CNL, -1, CR . $channel);    }    //推送聊天信息    private function _pushChatInfo($fd, $data, $guild = false){        if(!$guild){            $user = $this->redis->hGetAll(CF.$fd);            $fds = $this->redis->sMembers(CR . $user['channel']);            $this->redis->lPush(CL . $user['channel'],json_encode($data));            $type = 2;        }else{            $fds = $this->redis->sMembers(GR . $data['gid']);            $this->redis->lPush(GCL . $data['gid'],json_encode($data));            $type = 4;        }        $msg = array(            'msg_type'      => $type,            'uid'           => $data['uid'],            'name'          => $data['name'],            'data'          => $data['data'],            'level' => $data['level'],            'head'          => $data['head'],            'code'          => $type,        );        $this->ws->task(['fds'=>$fds,'msg'=>$msg]);        return [];    }    //初始化redis资源    private function _getRedis()    {        $redis = new Redis();        $redis->connect('127.0.0.1', 6379);        return $redis;    }}//启动new Ws();

请求示例

{"new_room":8,"old_room":1,"msg_type":1} //切换频道{"level":10,"data":"嗷嗷嗷啊","room_id":1,"msg_type":2,"uid":xxxx,"name":1028,"head":1}//聊天{"gid":xxxx,"uid":xxxx,"msg_type":0} //初始化,其实这块本来想写道open里面但是这样的话需要前端改动,就先这样了。

到此,关于"怎么用swoole + js + redis实现简易聊天室"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

频道 聊天室 简易 切换 学习 内容 代码 信息 更多 计数器 加密 帮助 接入 实用 接下来 这样的话 上代 人数 公会 前端 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 上海睿民互联网科技有限公司 湖南永感互联网科技有限公司 万易互联网科技 上海致骋互联网科技 兼蜜互联网科技 互联网科技素材视频竖屏 随着互联网科技发展 宁夏众和广鑫互联网科技有限公司 青岛科技大学互联网大赛研究生 知域互联网科技有限公司大骗子 互联网5g黑科技有哪些 深圳艾果互联网通讯科技 互联网在线教育科技创业 工业互联网等科技实现智能化赋能 怎样加入科技互联网 半导体是互联网高科技吗 南京一网一红互联网科技有限公司 科技互联网行业投资研究 上海万顺科技互联网有限公司招聘 美国五大互联网科技公司市值多少 科技赋能下的互联网金融 智网互联网科技 南京欣网互联网科技 狮子座互联网科技培训 富国互联网科技创新基金 恒银科技与互联网金融 互联网企业和科技型企业 互联网科技和法律行业 唐山双旺合互联网科技产业园 盐城市攀科互联网科技有限公司
0