既然可以设置缓冲区大小,如果缓冲区大小不是数据包大小的倍数会怎样?
一般来说,没有所谓的“数据包大小”。
因此,真正的问题是“如果到达的数据包不适合缓冲区中剩余的空间,会发生什么?”
对于 UN*Xes 上最常见的捕获机制(*BSD/macOS/AIX/Solaris 和 PF_PACKET 套接字中的 BPF 捕获机制),答案是“缓冲区被标记为已满并可供用户空间使用(即,运行 libpcap 循环的线程被唤醒,以便它可以读取缓冲区),并且,如果有任何其他可用的缓冲区,则将数据包放在下一个缓冲区的开头 - 如果没有可用的缓冲区,则数据包是掉了”。
即,使用这些数据包捕获机制,没有单个缓冲区,有两个或多个缓冲区(两个带 BPF 的缓冲区,多个带 PF_PACKET 套接字的缓冲区)。
使用 Windows 上 WinPcap/Npcap 使用的数据包捕获机制,有一个循环缓冲区,以及“当有这么多数据包数据可用时唤醒用户空间代码”量。如果缓冲区中的可用空间小于数据包的大小,则丢弃数据包。
“唤醒用户空间代码”的数量小于缓冲区大小,因此,如果数据到达的速度没有超过用户空间可以处理的速度,缓冲区应该被用户空间足够快地清空,以确保有足够的空间房间。
假设我有 500 字节的数据包,我的缓冲区是 800 字节
...那么您可能会丢弃 很多 个数据包。缓冲区应该比那个大很多。很久以前,BPF 的默认缓冲区大小是 32K 字节;现在是 256K 字节(这通常是操作系统支持的最大大小;实际上是两倍,因为有两个缓冲区)。 PF_PACKET 套接字的默认缓冲区大小为 2M 字节。
所以不要那样做。事实上,除非你看到很多丢包,或者在一个非常内存受限的机器上,否则不要设置缓冲区大小,让 libpcap 选择它给你。
(800 字节缓冲区大小不好的另一个原因 - 如果 CRC 不是捕获的数据包的一部分,则以太网上的最大数据包大小为 1514 字节,通常不是。缓冲区太小,无法即使缓冲区为空,保持最大大小的数据包也会丢弃这些数据包!)
现在假设我将缓冲区设置为 1000 字节,而数据包仍然是 500 字节。当两个数据包到达时,我的处理函数使用缓冲区调用,但如果一个新数据包到达,而我的处理函数仍在处理最后两个数据包,会发生什么?
见上文。
在我的处理函数处理完最后两个数据包之前,是否还有其他内部内核缓冲区仍会存储它,
如前所述,大多数 UN*X 上没有一个缓冲区,因此使用了另一个缓冲区 - 另一个 BPF 缓冲区或下一个 PF_PACKET 缓冲区。在 Windows 上,默认的“唤醒用户空间”数量使得其他数据包有足够的空间 - 只要缓冲区足够大,这是可能的。
请注意,原来的 libpcap 甚至没有设置缓冲区大小的例程 - 您只是获得了默认大小。