学习Muduo中Buffer的设计和网络编程buffer

Muduo中Buffer的设计和实现

1.为什么non-blocking 网络编程中应用层的buffer是必须的

non-blocking IO核心思想就是避免阻塞在read & write或者其他的IO系统调用上面,让一个线程能够服务多个socket连接。这样应用层次的缓冲是必须的。

TCPConnection有outputbuffer

场景:发送100KB的数据但是write()系统调用接受到了80KB的数据,就是TCP内核拥有一个发送的缓冲区,就是这次接受到了80KB,但是总不能在原地等待吧。那么剩下的20KB肿么办呢?

其实对于应用程序来说,它需要关心的不是发送分几次,这次发送完了没。它只需要知道它调用了发送send(),网路库能够帮忙完成就行了

网络库就有必要设置一个应用层的buffer了,这次的20KB换存在Buffer中,注册POLLOUT事件,一旦socket可写就往内核中发送数据。写完了就停止POLLOUT.

如果Buffer中还是有待发送的数据,但是程序想要关闭(他认为调用了send()就发送完了),但是网络库不能直接关闭,需要等待数据发送完成,TCP处于半连接状态

TCPConnection有inputbuffer

TCP是无边界的字节流协议,接收方需要处理 数据接受不能构成完整消息和一次性接受两条消息的情况

网络库在处理socket可读事件时候尽量一次性读取完成(这里使用的是LT模式),如果不读取完成会反复触发EPOLLIN事件,造成busy-loop.将buffer中的消息提取出来构成完整的消息再发送,当然TCP分包的情况在上一篇文章中Muduo ChatRoom介绍过了。

2.Muduo中Buffer设计

buffer中的inputbuffer & output buffer是针对于客户代码而言的,客户代码从inputbuffer读取, 往outputbuffer中写。tcpconnection的读写正好是相反的。

怎么设计并且使用缓冲区?

  • 我们希望系统调用的次数越少越好(那么缓冲区就要大一点才能一次性读取多一点)
  • 我们希望减少内存占用(那么缓冲区就要小一点,这样并发连接的总内存占用的少)

要满足这两个需求似乎是有点矛盾的,缓冲区究竟多大呢?

Muduo使用了一个很巧妙的方式:利用readv函数➕栈空间解决这个问题。(具体可以看我写的高级IO这一篇文章

  • 在栈空间准备65536字节(64KB)的buf,利用readv读取socket上的数据到iovec上面,iovec分别指向Muduo Buffer和栈上面的buffer.
  • 如果读的数据不多,直接放在muduo buffer,如果读的数据很多就放到栈空间,然后appendmuduo buffer上面,这样就完美的解决了

既然muduo buffer能动态调整大小,为什么还要这样做呢?

如果不利用栈空间的话,那么调用read的次数就太多了,利用栈空间就能一次性读取很多啦🤪

实现细节分析

  • 底层的存储使用vector进行存储,可以进行动态的扩容操作

  • 使用readIdx, writeIdx指针来表示可读和可写的区域

            缓冲区的模型:
 +-------------------+------------------+------------------+
 | prependable bytes |  readable bytes  |  writable bytes  |
 |                   |     (CONTENT)    |                  |
 +-------------------+------------------+------------------+
 |                   |                  |                  |
 0      <=      readerIndex   <=   writerIndex    <=     size
  • 增加了前置空间用于序列化等的时候进行操作头

从tcp读数据到buffer中

  • 使用了readv进行分散的读,将数据读到buffer & 栈空间
  • 从栈上面开辟大片的空间,如果不需要就用buffer,需要则将栈上暂存的写到buffer

请添加图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值