「TCP」- Transmission Control Protocol

  CREATED BY JENKINSBOT

建立连接(三次握手)

#0 Server

在创建连接前,Server 要处于 LISTEN 状态;

#1 Client => Server(第一次)

Client 向 Server 发送 SYN 数据包:SYN = 1, Sequence number = m
Client 进入 SYN-SENT 状态,等待匹配的连接请求;

#2 Client <= Server(第二次)

Server 向 Client 发送 SYN-ACK 数据包:SYN = 1, ACK = 1, Acknowledgment number = m + 1, Sequence number = n
Server 进入 SYN-RECEIVED 状态,等待请求确认;

#3 Client => Server(第三次)

Client 向 Server 发送 ACK 报文:ACK = 1, Sequence number = m + 1,Acknowledgment number = n + 1
Client 进入 ESTABLISHED 状态;

#4 Server

Server 收到 ACK 报文后,进入ESTABLISHED状态;

通过上述的三次报文发送,在 Client 与 Server 之间建立已知连接:
第(1)(2)步为一条连接建立连接参数(Sequence number),并且它是已知的;
第(2)(3)步为另一条连接建立连接参数(Acknowledgment number),并且它是已知的;

至此,一条全双工的连接就已经建立。

终止连接(四次挥手 / 三次挥手)

在终止连接时,任何一方都可以发起终止请求,不再分为 Server 和 Client 。我们使用 Initiator 代表 发起方 ,使用 Receiver 代表 接受方 。

#1 Initiator => Receiver

Initiator 向 Receiver 发送 FIN 报文:
发送之后,Initiator 进入 FIN-WAIT-1 状态:等待对端的连接终止请求,或者说连接终止请求已发送;

#2 Initiator <= Receiver

Receiver 向 Initiator 发送 ACK 报文:
发送之后,Receiver 进入 CLOSE-WAIT 状态:等待本地用户终止连接;

#3 Initiator <= Receiver

Receiver 向 Initiator 发送 FIN 报文:
发送之后,Receiver 进入 LAST-ACK 状态:等待之前发送到远程TCP的已知连接终止请求;
接收之后,Initiator 进入 FIN-WAIT-2 状态

#4 Initiator => Receiver

Initiator 向 Receiver 发送 ACK 报文:
发送之后,Initiator 进入 TIME-WAIT 状态:等待足够的时间以确保远程TCP收到连接终止请求。

#5 Receiver

接收之后,Receiver 进入 CLOSE 状态:

最后总结

共计 11 种状态,算上 UNKNOWN 共计 12 种状态。

关于 Seq 与 Ack 是如何增长的?

”只要发送数据包,序列号就会增长“,这个说法是错误的。正确的说法是”有效载荷存在,或者 SYN 设置,或者 FIN 设置,才会导致序列号增加“

1)发送 SYN、FIN、payload 数据包,都会导致 Seq 增加(作为下个数据包的 Seq 值);
2)ACK 值与上次收到的 payload 有关;

关于三次挥手

也可以通过三次挥手关闭连接(FIN, ACK+FIN, ACK),四次挥手只是常见的一种,各种实现上还会有所出入。

另外,服务器端收到客户端的 FIN 后,很可能还没发送完数据,所以就会先回复客户端一个 ACK 包。稍等一会儿,完成所有数据包的发送后,才会发送 FIN 包,这也就是四次挥手了。

半开连接

在等待客户端响应 ACK 的 TCP 连接被称为 半开连接。

相关链接

TCP delayed acknowledgment – Wikipedia
这是针对 TCP ACK 的一种优化机制。不用每次请求都发送 ACK 数据包,而是等待特定时间(40ms)后,如果存在其他待发送数据包,则同时发送。如果不存在其他数据包,则超时后单独发送。

Nagle 算法(纳格算法)
是 TCP 协议中用于减少小包发送数量的一种优化算法,目的是为了提高实际带宽的利用率。举个例子,当有效负载只有 1 字节时,再加上 TCP 头部和 IP 头部分别占用的 20 字节,整个网络包就是 41 字节,这样实际带宽的利用率只有 2.4%(1/41)。往大了说,如果整个网络带宽都被这种小包占满,那整个网络的有效利用率就太低了。Nagle 算法正是为了解决这个问题。它通过合并 TCP 小包,提高网络带宽的利用率。Nagle 算法规定,一个 TCP 连接上,最多只能有一个未被确认的未完成分组;在收到这个分组的 ACK 前,不发送其他分组。这些小分组会被组合起来,并在收到 ACK 后,用同一个分组发送出去。

参考文献

Wikipedia/Transmission Control Protocol
三次握手
How to Check TCP connections States in Linux with Netstat
Understanding TCP Sequence and Acknowledgment Numbers – PacketLife.net
38 | 案例篇:怎么使用 tcpdump 和 Wireshark 分析网络流量?