33.muduo学习笔记之net_TcpConnection.{h&cc}

1. 说明

  1. 一个TcpConnection类,代码有点长
  2. 使用了Channel,EventLoop,Socket,Buffer类
  3. 继承noncopyable,enable_shared_from_this,把当前对象转换成share指针,在connectEstablished()中有用到
  4. 在连接到来,创建一个TcpConnection对象,立刻使用shared_ptr来管理,引用计数为1.在Channel中维护一个weak_ptr(tie_),将这个shared_ptr对象赋值给tie_,引用计数仍为1.当连接关闭,在handleEvent,将tie_提升,得到一个shared_ptr对象
  5. 为什么使用那个weak_ptr呢,因为调用顺序是EventLoop–>Channel–>TcpConnection–>TcpServer,在TcpServer中移除TcpConnection,但此时Channel的handleEvent()还正在调用,直接删除TcpConnection对象会产生core dump错误,所以要让TcpConnection对象生命周期要长于handleEvent()函数
  6. 这里要解决高低水位的问题
    • 非阻塞网络编程中要注意发送数据的速度高于对方接受数据的速度,会造成数据在本地内存中的堆积,这带来设计及安全性方面的难度。Muduo对此解决办法是提供两个回调,有的网络库把它们称为“高水位回调”和“低水位回调”,Muduo使用HighWaterMarkCallback和WriteCompleCallback这两个作为高水位回调函数和低水位回调函数.调整发送频率,关注WriteCompleCallback,所有的数据都发送完,WriteCompleCallback回调,然后继续发送.
    • WriteCompleCallback
      如果发送缓存区被清空,就调用它。TcpConnection有两处可能触发此回调。
      TcpConnection::sendInLoop()。
      TcpConnection::handleWrite()。
    • HighWaterMarkCallback
      如果输出缓冲的长度超过用户指定大小,就会触发回调(只在上升沿触发一次)。在非阻塞的发送数据情况下,假设Server发给Client数据流,为防止Server发过来的数据撑爆Client的输出缓冲区,一种做法是在Client的HighWaterMarkCallback中停止读取Server的数据,而在Client的WriteCompleteCallback中恢复读取Server的数据。

2. 变量

  1. EventLoop* loop_;

    • 必备事件循环类
  2. const string name_;

    • 连接名字
  3. StateE state_; // FIXME: use atomic variable

    • 当前状态,值为最后所说的枚举类型中的几个选项
  4. bool reading_;

    • 判断通道是否可读
  5. std::unique_ptr socket_;

    • 客户端的socket_
  6. std::unique_ptr channel_;

    • 该连接所属的通道
  7. const InetAddress localAddr_;

    • 本地IP地址
  8. const InetAddress peerAddr_;

    • 连接过来的IP地址
  9. ConnectionCallback connectionCallback_;

  10. MessageCallback messageCallback_;

  11. WriteCompleteCallback writeCompleteCallback_;

  12. HighWaterMarkCallback highWaterMarkCallback_;

  13. CloseCallback closeCallback_;

    • 上面5个回调函数不再赘述
  14. size_t highWaterMark_;

    • 高水位标记
  15. Buffer inputBuffer_;

    • 应用层接受缓冲区
  16. Buffer outputBuffer_; // FIXME: use list as output buffer.

    • 应用层发送缓冲区
  17. boost::any context_;

    • 任意类型,一个未知类型的上下文对象
  18. 枚举类型

    • enum StateE

3. 函数

1. 私有

  1. void handleRead(Timestamp receiveTime);

    • 读回调,
  2. void handleWrite();

    • 写回调
  3. void handleClose();

    • 关闭连接的回调,设置状态,关闭通道,调用用户设置的回调
  4. void handleError();

    • 处理错误回调函数
  5. void sendInLoop(const StringPiece& message);

  6. void sendInLoop(const void* message, size_t len);

    • 就是往这个连接的对面write()写数据,把数据写给已连接套接字
    • 如果当前output缓冲区没有数据,就直接write(),写完的话如果有writeCompleteCallback_回调函数,就调用
    • remaining变量记录还有多少字节需要写,如果大于0的话,就加到outputBuffer_中,发出POLLOUT
    • 这里检测缓冲区数据是否大于highWaterMark_,如果大于并且有回调函数的话,调用这个高水位回调函数
  7. void shutdownInLoop();

    • 调用socket_->shutdownWrite();如果还有数据没发送完,就不能关闭.isWriting()是看是否有POLLOUT
    • 应用程序想关闭连接,但有可能正处于发送数据的过程中,output buffer 中有数据还没发完,不能直接调用close();
  8. void forceCloseInLoop();

    • 调用handleClose()
  9. void setState(StateE s) { state_ = s; }

    • 如名
  10. const char* stateToString() const;

    • 如名
  11. void startReadInLoop();

    • 使通道可读
  12. void stopReadInLoop();

    • 关闭通道可读

2. 公有

  1. 构造

    • 变量初始化,设置通道的几个回调函数
  2. 析构

    • 只打印日志
  3. EventLoop* getLoop() const

    • 返回loop_
  4. const string& name() const

    • 返回name_
  5. const InetAddress& localAddress() const

    • 返回localAddr_
  6. const InetAddress& peerAddress() const

    • 返回peerAddr_
  7. bool connected() const

    • 判断状态state是否_等于kConnected,即是否处于连接状态
  8. bool disconnected() const

    • 判断状态state是否_等于kDisconnected,即是否处于未连接状态
  9. bool getTcpInfo(struct tcp_info*) const;

    • 调用socket_->getTcpInfo(tcpi)获得tcp信息赋值到tcpi中
  10. string getTcpInfoString() const;

    • 返回tcp信息的string字符串
  11. void send(const void* message, int len);

  12. void send(const StringPiece& message);

  13. void send(Buffer* message); // this one will swap data

    • 以上几个send,总之就是调用sendInLoop(),不管同步还是异步
  14. void shutdown(); // NOT thread safe, no simultaneous calling

    • 把shutdownInLoop()加入到事件循环中
    • 设置状态,如果还有数据没写,shutdownInLoop()什么事都没做,以后服务端要根据状态再次调用shutdownInLoop()
  15. void forceClose();

    • 把forceCloseInLoop()加入循环
  16. void forceCloseWithDelay(double seconds);

    • 实际是调用foreclose()
  17. void setTcpNoDelay(bool on);

    • 如名
  18. void startRead();

    • 把startReadInLoop()加入事件循环
  19. void stopRead();

    • 把stopReadInLoop()加入事件循环
  20. bool isReading() const // NOT thread safe, may race with start/stopReadInLoop

    • 返回reading_
  21. void setContext(const boost::any& context)

  22. const boost::any& getContext() const

  23. boost::any* getMutableContext()

    • 以上三个是对Context的操作
  24. void setConnectionCallback(const ConnectionCallback& cb)

  25. void setMessageCallback(const MessageCallback& cb)

  26. void setWriteCompleteCallback(const WriteCompleteCallback& cb)

  27. void setHighWaterMarkCallback(const HighWaterMarkCallback& cb, size_t highWaterMark)

  28. void setCloseCallback(const CloseCallback& cb)

    • 以上五个如名,设置回调函数
  29. Buffer* inputBuffer()

  30. Buffer* outputBuffer()

    • 以上两个返回如名Buffer
  31. void connectEstablished(); // should be called only once

    • 连接建立时调用一次,设置状态state_,在channel_中使用tie()把当前对象赋值为一个weak_ptr,这样是为了让TcpConnection的生存周期比Channel长一点
    • 设置通道监听,调用连接回调函数,这个是用户指定的回调函数
  32. void connectDestroyed(); // should be called only once

    • 销毁连接,设置状态,调用用户的回调函数,移除通道
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值