用户区网络缓冲区
为什么要有用户层缓冲区
TCP内核协议栈,每个连接都有一个接收缓冲区和一个发送缓冲区,为啥用户层也要有:
- 为啥要有接收缓冲区
- 生产者速度大于消费者速度:客户端发送地太快,服务器处理不过来,需要先放到用户态缓冲区
- TCP基于流,需要进行粘包处理
- 为啥要有发送缓冲区
- 要发送的数据可能大于发送缓冲区剩余空间, n=send(fd,size),size-n就是需要置入缓冲区的数据
而对于UDP,其内核没有发送缓冲区,如果想实现udp可靠传输
,也需要设计用户态发送缓冲区、序列号、确认号、超时重传机制等
其次,UDP虽然基于报文传输,没有粘包问题,但还是需要面临内核协议栈接收缓冲区满的问题,因此,也需要设计用户态的接收缓冲区
用户缓冲区设计
以接收缓冲区为例:
- 定长缓冲区:一个数组,当前部分的数据被取走后,后面的数据需要往前移动,很麻烦
- 环形缓冲区:逻辑上环形,其实也是一个数组,进行取余操作,当缓冲区满时,追加的数据填充到前端;可以将数组的长度设置为2^n,这样就可以将数组的取余运算转换为位运算
- 有个缺点:数据分散问题,数据可能一部分在数组尾部,一部分在数组头部,需要accept两次
- 假设是发送缓存区,分散的数据要分两次send到内核发送缓冲区,同样是两次系统调用
- 链式缓冲区:多个数组链接起来,缓冲区满了时在后面新增一个数组。(这样还是可能产生数据分散的问题,需要accept两次)