以前一直有这么一个小小的疑惑,当一个进程注册一个套接字后,那么这个进程每次调用recv系函数接收数据的时候,接收的是执行recv期间收到的数据还是一定时期内收到的数据? 或者这样说,如果我的程序收到一个数据包后需要很长一段时间处理,然而在某段时间又突然有一大批包在很短的时间内发过来(短过数据包的处理时间),那我的程序会不会漏过某些数据包(那个包到达的时候程序在处理别的包,而没有调用recv函数)?
答案是不会的。事实上linux中会为每个套接字建立缓存,当属于套接字的包到达的时候,只要这个套接字已经被注册,不管你当时有没有调用recv函数,数据包都会被存在套接字的缓存中(实际上是一个skb结构链表),只要缓存没被填满,你可以随时调用recv函数从缓存中取出数据包处理。本人经过实验发现,数据包在缓存中停放的时间是很长的,个人推测应该是直到这个套接字被关闭。
说到这里的缓存,研究过tcpip的人一定能想到tcp中的滑动窗口流量控制。没错,那里的窗口大小值其实就是你的套接字当前的剩余缓存大小值。默认下套接字的初始缓存大小为8192字节,当然,这个也是可以用套接字选项去调整的。