SWOOLE开发实时聊天系统(十)用户断开聊天

栏目: IT技术 · 发布时间: 6年前

内容简介:最后我们再处理一下用户断开连接的时候的处理工作。首先,我们需要在websocket断开的时候,去调用MessageController中的close函数,传递当前用户的fd.在MessageController中,去调用处理用户登录注册所有逻辑的LoginService处理具体的业务逻辑,删除用户和直播的关系。其中包括删除user_id 对应的fd,group对应的fd等的内容。

最后我们再处理一下用户断开连接的时候的处理工作。

首先,我们需要在websocket断开的时候,去调用MessageController中的close函数,传递当前用户的fd.

$this->server->on('close', function ($ser, $fd) {
            echo "server: close a fd  : fd{$fd}\n";
            $this->MessageController->closeFd($fd);
        });

在MessageController中,去调用处理用户登录注册所有逻辑的LoginService处理具体的业务逻辑,删除用户和直播的关系。其中包括删除user_id 对应的fd,group对应的fd等的内容。

//关闭连接
    public function closeFd($fd)
    {
        $loginService = new LoginService($this->server);
        $loginService->close($fd);
    }

然后我们去LoginService中完成逻辑处理:

public function close($fd) {
        try{
            $result=$this->removeFromRedis($fd);
            if(!$result){
                throw new \Exception('删除用户失败,请重试!');
            }
            //在这里也加上notify,如果有需要通知的内容,可以在前面直接写,不用再更改此处的业务逻辑
            $this->notify();
        }catch (\Exception $e){
            $this->result['status'] = 1;
            $this->result['msg'] = $e->getMessage();
            echo json_encode($this->result,JSON_UNESCAPED_UNICODE);
        }
        return $this->result;
    }

具体的实现方法如下:

private function removeFromRedis($fd){
        $user_id = pool::redis()->hGet(self::user_bind_redis_key, $fd);
        pool::redis()->hDel(self::user_bind_redis_key, $fd);
        //删除当前用户所对应的分组
        $rk = str_replace('fd', $fd, self::redis_key_user_group);
        $group = pool::redis()->get($rk);
        pool::redis()->del($rk);
        //删除分组中对应的用户
        if ($group) {
            $group = explode("_", $group);
            //从分组对应的用户中,删除当前用户
            $rk = str_replace(['first_topic', 'second_topic'], [$group[0], $group[1]], self::redis_key_group_user);
            $userlist = pool::redis()->get($rk);
            $userlist = explode(',', $userlist);
            $key = array_search($user_id, $userlist);
            array_splice($userlist, $key, 1);
            if (!$userlist) {
                pool::redis()->del($rk);
            } else {
                pool::redis()->set($rk, implode(",", $userlist));
            }
        }
        //删除fd绑定的用户。
        pool::redis()->hDel(self::fd_bind_user_redis_key, $user_id);
        return true;
    }

在这段逻辑中主要是通过fd来查找之前我们生成的所有缓存内容,将所有与当前fd相关的内容全部删除。也就使得用户与我们的业务脱离了关系。

当两个用户都连接之后,我们可以看到,redis中一共有如下几个Key:

1) "ws_topic_1_1"
2) "ws_user_2"
3) "ws_fd_bind_user_redis_key"
4) "ws_user_bind_fd_redis_key"
5) "ws_user_4"

我们打开其中的一个去查看,可以发现,两个用户ID正好对应两个fd

127.0.0.1:6379> hkeys ws_fd_bind_user_redis_key
1) "10086"
2) "10087"
127.0.0.1:6379> hget ws_fd_bind_user_redis_key 10086
"2"
127.0.0.1:6379> hget ws_fd_bind_user_redis_key 10087
"4"

然后我们试着关闭10087的用户

再去查看 redis 中的内容

127.0.0.1:6379> keys *
1) "ws_topic_1_1"
2) "ws_user_2"
3) "ws_fd_bind_user_redis_key"
4) "ws_user_bind_fd_redis_key"

127.0.0.1:6379> hkeys ws_fd_bind_user_redis_key
1) "10086"

127.0.0.1:6379> hkeys ws_user_bind_fd_redis_key
1) "2"
127.0.0.1:6379>

所有关于用户10087的内容都已经被删除了。

至此,整个业务流程全部完成。

项目已经放在了github上,欢迎大家批评指正。 https://github.com/gsbhx/swoole_chat

下一步,计划使用Golang实现一下这一功能。


以上所述就是小编给大家介绍的《SWOOLE开发实时聊天系统(十)用户断开聊天》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Probability and Computing

Probability and Computing

Michael Mitzenmacher、Eli Upfal / Cambridge University Press / 2005-01-31 / USD 66.00

Assuming only an elementary background in discrete mathematics, this textbook is an excellent introduction to the probabilistic techniques and paradigms used in the development of probabilistic algori......一起来看看 《Probability and Computing》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具