ascs 简明开发教程(四):多连接管理(服务端)

31 篇文章 1 订阅
31 篇文章 0 订阅

QQ交流群:198941541

服务端天生支持多连接,想只支持一条连接反而需要额外的工作量,这个我们留到讲服务端启动优化时再说,敬请期待。

由于服务端连接是被动生成的,所以它不能像客户端那样管理连接(仅限于ascs 简明开发教程(3)里面介绍的方法)。为此你必须建立自己的映射关系,先说说ascs的多连接管理原理:

每个新接收到的连接,服务端会得到一个server_socket_base对象并为其分配一个唯一的id(称之为ascs id),64位整数,永远自增不复用(即便是server_socket_base被复用时,也不复用ascs id),然后放在hash map里面(由object_pool实现,server_base继承自它,以后会有详细的对object_pool的介绍,敬请期待),如果你想在socket之外找到一个socket(比如在main函数里面找到一个socket并调用其send_msg,或者在一个socket里面找到另外一个socket并调用其send_msg),就得提供ascs id。假设你的id统称logic id(你必须有,它可以也是个整数,或者字符串,否则你也不知道找谁),那么客户端上线之后,肯定会发一个类似注册的消息(否则你怎么知道谁是谁?),你解析这个消息并得到logic id,注意此时是在socket内部,你应该在此时建立ascs id与logic id的对应关系,比如:

extern std::mutex mutex;
extern std::unordered_map<int, uint_fast64_t> user_map;
virtual bool on_msg_handle(out_msg_type& msg)
{
    if (is_register_msg(msg))
    {
        std::lock_guard<std::mutex> lock(mutex);
        user_map[get_id(msg)] = id(); //ascs id
    }
}

当想要查找socket时(s是一个server_base对象):

extern std::mutex mutex;
extern std::unordered_map<int, uint_fast64_t> user_map;
bool send_msg_to(const std::string& msg, int logic_id)
{
    std::shared_lock<std::mutex> lock(mutex);
    auto iter = user_map.find(logic_id);
    if (iter != std::end(user_map);
    {
        auto ascs_id = iter->second;
        lock.unlock();

        auto socket_ptr = s.find(ascs_id);
        return socket_ptr && socket_ptr->send_msg(msg);
    }

    return false;
}

可以看到,我们做了两次hash map查找,一是对user_map的查找,一是对socket的查找(s.find()调用),效率问题不用担心,因为hash map查找是 O(1)的效率,两次也就两个O(1)而已(除非你有意造重复hash code)。如果你还是担心,则可以(其中s_socket来自ascs 简明开发教程(2)):

extern std::mutex mutex;
extern std::unordered_map<int, std::shared_ptr<s_socket> user_map;
virtual bool on_msg_handle(out_msg_type& msg)
{
    if (is_register_msg(msg))
    {
        std::lock_guard<std::mutex> lock(mutex);
        user_map[get_id(msg)] = share_from_this();
    }
}

那么查找的时候,你一次查询user_map就能得到socket,无需再调用s.find()。这种方法要注意一点,当连接断开时(如何得到及处理连接断开,以后会有介绍,敬请期待),需要把socket从user_map里面删除,否则这个socket将无法被object_pool释放或者重用。

上面说的连接管理方法(两种实现)同样适用于用multi_client管理的多连接的管理(multi_client同样继承自object_pool,所以它也有find函数),在调用add_socket之后(记不起来的话可以重温ascs 简明开发教程(3)),ascs id已经生成且不会再改变(即便发生了重连接之后,如何控制client_socket的重连接,以后会有介绍,敬请期待),此时你就可以得到ascs id并存入user_map,因为此时你已经可以生成你的logic id了,这条连接的属性已经确定了,只是还没连接成功而已,如果你非要在连接成功之后存入user_map,则你需要重写虚函数client_socet::on_accept并在里面存user_map,重写client_socket::on_recv_error并在里面从user_map里面清除。

现在回答一下ascs 简明开发教程(3)里面提的一个问题,multi_client到底有什么用?上面说了,multi_client同样继承自object_pool,所以它也有对象管理和重用的功能(以后还会专门介绍object_pool,敬请期待)。其次,如果你需要给所有连接发送同样一条消息,用multi_client会更简单(注意,广播消息时,会有锁,如果你不会动态增减连接,那么锁是不必要的,此时用single_client + std hash map自己管理连接,在广播消息这个功能上,会更有效)。

上一篇:ascs 简明开发教程(3)下一篇:ascs简明开发教程(5)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值