ZLToolKit源码阅读:套接字封装

1059 篇文章 285 订阅

套接字抽象封装,包含TCP服务器、TCP客户端(TCP session)、UDP套接字、与EventPoller关联处理描述符事件,数据发送以及接收处理等。

概述

在这里插入图片描述
在这里插入图片描述
以上,是套接字封装模块的类图以及每个类的大致功能,上层使用最多的是Socket和SocketHelper两个类。

功能分析

SockNum

  • 它有两个成员函数:
    • _fd :
      • 构造函数中初始化
      • 析构函数中关闭
    • _type :fd的类型,构造函数中指定,指定后不可更改

就是简单的包装了一下_fd而已

class SockNum {
public:
    using Ptr = std::shared_ptr<SockNum>;

    typedef enum {
        Sock_Invalid = -1,
        Sock_TCP = 0,
        Sock_UDP = 1
    } SockType;

    SockNum(int fd, SockType type) {
        _fd = fd;
        _type = type;
    }

    ~SockNum() {
        ::shutdown(_fd, SHUT_RDWR);
        close(_fd);
    }

    int rawFd() const {
        return _fd;
    }

    SockType type() {
        return _type;
    }

    void setConnected() {
    }



private:
    int _fd;
    SockType _type;
};

SockFD

这玩意啥也没有干呀,就是在析构的时候不再监听fd,并关闭fd而已。

注意,这里的fd不是在这个类中设置被EventPoller监听的,仅仅在析构是不监听fd了

//socket 文件描述符的包装
//在析构时自动溢出监听并close套接字
//防止描述符溢出
class SockFD : public noncopyable {
public:
    using Ptr = std::shared_ptr<SockFD>;

    /**
     * 创建一个fd对象
     * @param num 文件描述符,int数字
     * @param poller 事件监听器
     */
    SockFD(int num, SockNum::SockType type, const EventPoller::Ptr &poller) {
        _num = std::make_shared<SockNum>(num, type);
        _poller = poller;
    }

    /**
     * 复制一个fd对象
     * @param that 源对象
     * @param poller 事件监听器
     */
    SockFD(const SockFD &that, const EventPoller::Ptr &poller) {
        _num = that._num;
        _poller = poller;
        if (_poller == that._poller) {
            throw std::invalid_argument("copy a SockFD with same poller!");
        }
    }

    ~SockFD() {
        auto num = _num;
        _poller->delEvent(_num->rawFd(), [num](bool) {});
    }

    void setConnected() {
        _num->setConnected();
    }

    int rawFd() const {
        return _num->rawFd();
    }

    SockNum::SockType type() {
        return _num->type();
    }

private:
    SockNum::Ptr _num;
    EventPoller::Ptr _poller;
};

socket

在这里插入图片描述
Socket封装了针对文件描述符的各种操作,包括TCP与UDP套接口基础概念封装、数据的发送与接收控制、事件回调处理等。

Socket可用于TCP Server监听(listen socket)、TCP Server会话(accept后的socket)、TCP Client、UDP Server/Client类型。

构造&&析构

socket构造函数

啥也没有干,仅仅重置了一下成员函数

  • 声明:
    Socket(const EventPoller::Ptr &poller = nullptr, bool enable_mutex = true);
  • 实现:
Socket::Socket(const EventPoller::Ptr &poller, bool enable_mutex) :
        _mtx_sock_fd(enable_mutex), _mtx_event(enable_mutex),
        _mtx_send_buf_waiting(enable_mutex), _mtx_send_buf_sending(enable_mutex){

    _poller = poller;
    if (!_poller) {
        _poller = EventPollerPool::Instance().getPoller();
    }
    setOnRead(nullptr);
    setOnErr(nullptr);
    setOnAccept(nullptr);
    setOnFlush(nullptr);
    setOnBeforeAccept(nullptr);
}

析构函数&&closeSock

啥也没有干,就是清理了一下资源

#define LOCK_GUARD(mtx) lock_guard<decltype(mtx)> lck(mtx)

Socket::~Socket() {
    closeSock();
}

// closeSock
void Socket::closeSock() {
    _con_timer = nullptr;
    _async_con_cb = nullptr;

    LOCK_GUARD(_mtx_sock_fd);
    _sock_fd  = nullptr;
}
createSocket
  • 声明
    /**
     * 构造socket对象,尚未有实质操作
     * @param poller 绑定的poller线程
     * @param enable_mutex 是否启用互斥锁(接口是否线程安全)
    */
    static Ptr createSocket(const EventPoller::Ptr &poller = nullptr, bool enable_mutex = true);
  • 实现
Socket::Ptr Socket::createSocket(const EventPoller::Ptr &poller, bool enable_mutex){
    return std::make_shared<Socket>(poller, enable_mutex);
}

啥也没有干,就是调用了一些socket的构造函数

仅用于TCP Server监听

listen

仅用于TCP Client

connect:创建tcp客户端并异步连接服务器

(1)因为我们是要创建一个新的连接,所以第一步应该是先清理一下之前的设置(将之前打开的资源关闭)

   //重置当前socket
    closeSock();

从上面我们也可以推测出,这个类是可以复用的
(2)第二步,我们要知道这个类它是继承了std::enable_shared_from_this<Socket>

//异步IO Socket对象,包括tcp客户端、服务器和udp套接字
class Socket : public std::enable_shared_from_this<Socket> {
}

为什么要继承std::enable_shared_from_this<Socket>呢?因为这用于异步操作,因为在异步调用中,异步函数执行的时间点我们是无法确定的,然而异步函数可能会使用到异步调用之前就存在的变量。为了保证该变量在异步函数执期间一直有效,我们可以传递一个指向自身的share_ptr给异步函数,这样在异步函数执行期间share_ptr所管理的对象就不会析构,所使用的变量也会一直有效了(保活)。怎么包含呢?从

    weak_ptr<Socket> weak_self = shared_from_this();

SockFD、SocketNum、Socket关系

描述符封装,SockNum作为SockFD的成员变量,SockFD作为Socket的成员变量。

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值