网络缓冲区的4种实现方法

一、概述

网络缓冲区用于缓冲待发送的数据或接收了待处理的数据,发送缓冲区可以积累一定量的数据再发送,接收缓冲区可以积累一定量的数据,解决粘包导致的没有收到完整的数据包,缓冲起来等包数据完整了再提交给业务逻辑处理。

二、实现方案

根据我的经验,这里将介绍四种实现机制,包括单块连续内存缓冲,环形缓冲,环形分块缓冲,链表分块缓冲。

1. 单块连续内存缓冲
单块连续缓冲是最简单地实现机制。这种方案采取一块连续的内存来作为缓冲区,随着数据的写入和读取,有效数据块会逐渐往后移动,在合适的时机把整块有效数据移动到头部。如果整块内存都被写完,也可以新分配一块更大内存,并把老的块上数据拷贝过来,并释放掉老的块,具体的实现,看下图。
网络缓冲区的4种实现方法_第1张图片

2. 环形缓冲区
环形缓冲区也是一块连续内存,与第一种方案的区别是end到达内存块尾部时,end可以移动到块的头部,可以无限接近start,但不会超过start。相比第一种方案,当数据写到内存块得的尾部时,不需要拷贝整块有效数据到头部。如果环形缓冲区是固定大小,支持一个线程读,另一个线程写的无锁操作。
网络缓冲区的4种实现方法_第2张图片
3. 环形分块缓冲
分块环形缓冲也采用了环形结构,不过环形的每个元素不是一个字节,而是一个内存块(每个内存块可以是固定大小,方便做内存池,也可以采用不同的大小)。没有内存块可写入的时候,会分配一个内存块,当一块内存上的数据都被读取的,可以释放掉这个内存块。这种实现避免了单块内存的最大内存限制(不能超过2G),可以支持最大2G*2G的缓冲区。相对前两种方案,不需要考虑扩容、缩容问题,可以更快捷地分配和释放内存,更有效地利用内存。
网络缓冲区的4种实现方法_第3张图片
4. 链表分块缓冲
libevent的缓存区实现采用了这种机制。跟环形分块缓冲类似,但不采用环形缓冲,而是采用将内存块前后连接起来,有点类似环形分块缓冲,相比环形分块缓冲有一个优点,不需要预先分配一个缓冲缓冲区。
网络缓冲区的4种实现方法_第4张图片

三、总结

如果缓冲区的最大大小能预估,且大小比较小,比如5MB,那么采用方案一和二比较好。如果缓冲区的大小不能预估,大小差别较大,用方案三和四比较好,不过实现的复杂度也相对高不少。

你可能感兴趣的:(游戏引擎,网络通信,网络缓冲区,环形缓冲,libevent缓冲区,缓冲区实现)