真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

怎么用swoole+js+redis實現(xiàn)簡易聊天室

這篇文章主要介紹“怎么用swoole + js + redis實現(xiàn)簡易聊天室”,在日常操作中,相信很多人在怎么用swoole + js + redis實現(xiàn)簡易聊天室問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么用swoole + js + redis實現(xiàn)簡易聊天室”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)建站!專注于網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、重慶小程序開發(fā)、集團企業(yè)網(wǎng)站建設(shè)等服務(wù)項目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了饒平免費建站歡迎大家使用!

公司需要用到在線聊天功能,先寫了個demo出來展示效果。

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

聊天室分為10個頻道,可以切換頻道,頻道計數(shù)等。

目前還沒做聊天內(nèi)容的加密。

按需求,聊天內(nèi)容可能會每個頻道保留最近一百條,聊天加密的話考慮aes,也有可能不加。后續(xù)看情況了。

目前還沒做異常處理。回頭繼續(xù)完善之后可能會再進行更新。

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




    
    WebSocketTestPage
    








服務(wù)端代碼

  ['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";
    }

    //初始化頻道計數(shù)器
    private function _resetChatNum(){
        for($i = 1; $i <= CHANNEL_MAX_SIZE; $i++){
            $this->redis->zAdd(CNL, 0, CR . $i);
        }
    }

    //獲取人數(shù)最少頻道
    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;
    }


    //連接時設(shè)置推薦頻道
    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,
        );
    }

    //設(shè)置頻道相關(guān)數(shù)據(jù)
    private function _setChannelInfo($fd, $channel){
        //存入fd
        $this->redis->sAdd(CR . $channel,$fd);
        //變更計數(shù)器
        $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,
        );
    }

    //關(guān)閉連接時清除相關(guān)內(nèi)容
    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里面但是這樣的話需要前端改動,就先這樣了。

到此,關(guān)于“怎么用swoole + js + redis實現(xiàn)簡易聊天室”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
網(wǎng)頁名稱:怎么用swoole+js+redis實現(xiàn)簡易聊天室
標題來源:http://weahome.cn/article/gdjsjj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部