重点是这句 “Data or controls which were queued for transmission may be included”,也就是说标准表示,第三次握手的 ACK 包是可以携带数据。那么 Linux 的内核协议栈是怎么做的呢?侯捷先生说过,“源码面前,了无秘密”。最近恰逢 Kernel 4.0 正式版发布,那就追查下这个版本的内核协议栈的源码吧。
在探索源码前,我们假定读者对 Linux 的基本 socket 编程很熟悉,起码对连接的流程比较熟悉(可以参考这篇文章《浅谈服务端编程》最前边的 socket 连接过程图)。至于 socket 接口和协议栈的挂接,可以参阅《socket 接口与内核协议栈的挂接》。
首先, 第三次握手的包是由连接发起方(以下简称客户端)发给端口监听方(以下简称服务端)的,所以只需要找到内核协议栈在一个连接处于 SYN-RECV(图中的 SYN_RECEIVED)状态时收到包之后的处理过程即可。经过一番搜索后找到了,位于 net\ipv4 目录下 tcp_input.c 文件中的 tcp_rcv_state_process 函数处理这个过程。如图: