handy : TcpConn

https://github.com/yedf/handy/blob/master/handy/conn.h

enable_shared_from_this

struct TcpConn: public std::enable_shared_from_this<TcpConn>, private noncopyable

TcpConn继承了std::enable_shared_from_this<TcpConn>,使得TcpConn可以安全的向外传递自己的智能指针,而不是传出一个危险的裸指针。

可以参考这里学习:

http://www.cplusplus.com/reference/memory/enable_shared_from_this/?kw=enable_shared_from_this

成员变量

    public:
        EventBase* base_;   // 事件循环
        Channel* channel_;  // 已连接套接字对应的Channel
        Buffer input_, output_; // 输入/输出缓冲区
        Ip4Addr local_, peer_;
        State state_;  // 状态
        TcpCallBack readcb_, writablecb_, statecb_; // 一些回调函数
        std::list<IdleId> idleIds_;
        TimerId timeoutId_;
        AutoContext ctx_, internalCtx_;
        std::string destHost_, localIp_;
        int destPort_, connectTimeout_, reconnectInterval_;
        int64_t connectedTime_;
        std::unique_ptr<CodecBase> codec_;

TcpConn表示一个Tcp连接。channel_表示已连接套接字对应的Channel。
muduo对于非阻塞网络编程为什么需要输入/输出缓冲区做了很详细的解释。(chapter 6.4 P137有讨论)。handy作为一个非阻塞的网络库自然有输入/输出缓冲区。

此外,handy使用状态机描述一个连接的生命期:

//Tcp连接的个状态
enum State { Invalid=1, Handshaking, Connected, Closed, Failed, };

构造函数/析构函数

TcpConn::TcpConn()
    :base_(NULL), 
    channel_(NULL), 
    state_(State::Invalid), // 初始状态为 Invalid
    destPort_(-1),
    connectTimeout_(0),
    reconnectInterval_(-1),
    connectedTime_(util::timeMilli())
{
}

TcpConn::~TcpConn() {
    delete channel_; // 析构channel
}

TcpConn::attach

上一篇的最后提到了TcpServer对TcpConn的使用。TcpConn被创建后,调用的第一个函数就是attach。

void TcpConn::attach(EventBase* base, int fd, Ip4Addr local, Ip4Addr peer)
{
    fatalif((destPort_<=0 && state_ != State::Invalid) || (destPort_>=0 && state_ != State::Handshaking),
        "you should use a new TcpConn to attach. state: %d", state_);
    base_ = base;
    state_ = State::Handshaking;
    local_ = local;
    peer_ = peer;
    if (channel_) { delete channel_; }

    // 创建一个Channel,向Poller注册已连接套接字的可读和可写事件
    channel_ = new Channel(base, fd, kWriteEvent|kReadEvent);
    trace("tcp constructed %s - %s fd: %d",
        local_.toString().c_str(),
        peer_.toString().c_str(),
        fd);

    // 获得自己的shared_ptr
    TcpConnPtr con = shared_from_this();

    // 设置读写回调函数
    con->channel_->onRead([=] { con->handleRead(con); });
    con->channel_->onWrite([=] { con->handleWrite(con); });
}

attach函数的作用就是,创建一个关于已连接套接字的Channel,并设置好读写回调函数。可以说TcpConn也是Channel和EventBase的使用者。

思考一些问题

从accept得到的socket这里称为已连接套接字,它们是在哪里被close的呢?

答案:是在Channel的析构函数被调用时。当TcpConn被销毁时,Channel会被delete,socket就在析构函数执行是被关闭了。虽然socket的创建不是在Channel中,但是关闭却需要Channel来执行,显得有些不对称。muduo中的socket是一个RAII,可能更好吧。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值