handy : TcpConn

来源:互联网 发布:表白网站制作软件 编辑:程序博客网 时间:2024/06/03 02:26

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