文章目录
- 昨日内容复习
- TCP 的头部结构
- TCP 如何保证可靠传输?
- 详述 TCP 三次握手的过程?
- TCP 为什么要三次握手?
- TCP 三次握手中发生丢包怎么办?
- 复习计算机网络 Day2:TCP 断开连接时四次挥手及其相关问题
- TCP 的四次挥手?
- TCP 为什么要四次挥手?
- 在客户端处于 FIN_WAIT_2 状态时,如果此时收到了乱序的来自服务端的 FIN 报文,客户端会如何处理?何时进入 TIME_WAIT 状态?
- TCP 的四次挥手丢了怎么办?
- TCP 的延迟应答和累积应答?
- TCP 会出现三次挥手吗?
- TCP 的 MSL?
昨日内容复习
昨天对 TCP 的头部结构、TCP 如何实现可靠传输以及 TCP 的三次握手进行了回顾。
在此可以先简单回顾一下,避免遗忘。
TCP 的头部结构
TCP 的头部结构占 20 个字节,主要由源端口和目的端口(各占 16 位)、序列号(32 位)、确认号(32 位)、紧急指针(16 位)、滑动窗口大小(16 位)、标志位、保留位(6 位)、头部长度(4 位)、校验和(16 位)、可选项及数据部分构成。
其中我个人认为最重要的两个字段是序列号和确认号,序列号标识了当前报文数据部分的每个字节(存在一个特殊情况,那就是请求连接报文 SYN 和请求结束报文 FIN 会隐式地占据一个序列号,用于同步);确认号标识了当前接收方期望接收到发送方的下一个序列号是多少,加入确认号为 x
,那么代表序列号为 x-1
及其之前的数据已经收到。
TCP 如何保证可靠传输?
- TCP 在传输的过程中,通过头部结构的序列号与确认号确保数据传输的顺序性和可靠性;
- TCP 报文的头部结构中有一个校验和字段,它同时使用头部结构和数据部分计算校验和,接收方通过相同的方法在接收数据后计算校验和并与头部中的校验和进行对比;
- TCP 在传输的过程中,接收方会首先将接收到的数据放在缓冲区当中进行排序,将排序过后的数据发送给应用层;
- TCP 通过三次握手建立可靠连接,通过四次挥手确保连接断开;
- TCP 有超时重传机制,连续发送三个相同的 ACK 报文代表紧急重传;
- TCP 传输带有流量控制和拥塞控制,具体来说,通过设置报文头部的滑动窗口字段来告知对方当前自己缓冲区的可用大小,发送方可以据此动态地调节发送数据的频率,避免丢包。此外,在连接刚刚建立时,发送方发送数据的长度会以指数级增长,当发生丢包时再将发送数据的长度减半,丢失的数据快速重传,以实现拥塞控制。
详述 TCP 三次握手的过程?
- 第一次握手:客户端发送 SYN 置位的报文,该报文的序列号为
x
,发送后客户端进入 SYN_SENT 状态; - 第二次握手:服务端接收到客户端发送的 SYN 报文,转而发送 SYN-ACK 报文,该报文的序列号为
y
,确认号为x + 1
,发送后服务端进入 SYN_RECV 状态; - 第三次握手:客户端接收到 SYN-ACK 报文后,向服务器发送 ACK 报文,序列号为
x + 1
,确认号为y + 1
,之后进入 ESTABLISHED 状态。服务端接收到 ACK 后也进入 ESTABLISHED 状态。
TCP 为什么要三次握手?
- 三次握手使得服务端和客户端互相知道自己和对方的收发能力是正常的;
- 三次握手可以避免由于网络拥塞造成的连接重复建立,避免不必要的资源浪费;
TCP 三次握手中发生丢包怎么办?
- 第一次握手丢失:客户端发送的 SYN 报文丢失,触发超时重传直到重传次数上限;
- 第二次握手丢失:服务端发送给客户端的 SYN-ACK 报文丢失,客户端会认为自己发送的 SYN 报文没有到达服务端,因为这个 SYN 报文没有被确认,而服务端没有收到客户端的 ACK 报文,因此客户端和服务端同时开启超时重传;
- 第三次握手丢失:客户端发送 ACK 报文后进入 ESTABLISHED 状态,由于该 ACK 丢失,服务端会重传 SYN-ACK,客户端收到后重传 ACK。
「注意」 在 TCP 连接当中,ACK 报文丢失,发送 ACK 报文的一方不会重传 ACK 报文,而是接收方发现自己方才发送的报文没有得到确认,遂重发刚才的报文,接收方接收到重发的报文后才再次发送 ACK 报文对其进行确认。
复习计算机网络 Day2:TCP 断开连接时四次挥手及其相关问题
TCP 的四次挥手?
为了方便描述,我们以客户端作为主动关闭方,服务端作为被动关闭方。
第一次挥手
客户端发送释放报文,并停止发送数据,该报文的 FIN 置位,报文的序列号为 x = u
,u
的值是之前发送的数据的最后一个字节的序列号加一。此时客户端进入 FIN_WAIT_1 状态。需要注意的是,即使 FIN 报文不携带数据,也要占用一个序列号,与 SYN 报文相似。
第二次挥手
服务端接收到 FIN 报文后,发送 ACK 报文确认刚才收到的 FIN 报文,仅置位 ACK,报文的确认号为 u + 1
,序列号为 v
,然后服务端进入 CLOSED_WAIT 关闭等待状态。此时 TCP 协议将会通知应用层,客户端向服务器请求连接释放了。客户端现在已经处于半关闭状态,不能发送数据,但是仍然可以接收数据。客户端的半关闭状态需要持续一段时间,直到服务端的 CLOSED_WAIT 状态结束。
客户端在收到服务端的 ACK 报文后,进入 FIN_WAIT_2 状态,等待服务器发送 FIN 报文。
第三次挥手
服务器处理完数据之后,向客户端发送 FIN 报文,该报文的确认号为 u + 1
,由于方才服务端在处理数据时可能发送了一些数据,因此此时该报文的序列号我们记为 w
。发送 FIN 报文后,服务端进入 LAST_ACK 状态。
第四次挥手
客户端收到服务器的 FIN-ACK 报文后,会发送 ACK 报文,序列号为 u + 1
,确认号为 w + 1
。
发送后客户端进入 TIME_WAIT 状态。此时 TCP 连接还没有释放,需要经过两个 MSL 时间(MSL 指的是报文最长寿命),之后客户端才进入 CLOSED 状态。
服务端接收到客户端的 ACK 报文后,立即进入 CLOSED 状态,TCP 连接至此结束。
TCP 为什么要四次挥手?
确保全双工通信的独立关闭
由于 TCP 连接是一个双向数据通道,一方发送 FIN 仅表示自己方向不再发送数据,但是另一个方向仍然可能有数据待发送。因此需要分别关闭两个方向的发送通道,分别通过第一次挥手客户端向服务端发送 FIN 报文以及第三次挥手服务端向客户端发送 FIN-ACK 报文来完成。
确保数据完整性
TCP 断开连接的第二次挥手是服务端向客户端发送 ACK 报文以确认客户端的 FIN 报文,而第四次挥手是客户端发送 ACK 报文确认服务端发送的 FIN 报文。这两次挥手发送的 ACK 报文可以确保双方得知自己的 FIN 报文被收到了,故不再重传 FIN 报文以避免资源浪费。
对比三次挥手
TCP 连接建立时可以三次握手来完成是因为第二次握手时服务端发送的是 SYN-ACK 报文,SYN 和 ACK 同时置位使得服务端只需要发送一次数据。
而四次挥手时,服务端不能发送 FIN-ACK 报文,而是需要先发送 ACK 报文确认客户端的 FIN 报文,然后处理剩余的数据并发送,再发送 FIN 报文关闭自己方向上的连接。
因此四次挥手的原因重点就在于 FIN 和 ACK 不能在服务端合并发送,因为可能存在尚未发送完毕的数据。
在客户端处于 FIN_WAIT_2 状态时,如果此时收到了乱序的来自服务端的 FIN 报文,客户端会如何处理?何时进入 TIME_WAIT 状态?
客户端在接收到服务端确认其 FIN 报文的 ACK 报文后进入 FIN_WAIT_2 状态,接收到服务端的 FIN 报文后发送 ACK 报文对其进行确认,随即进入 TIME_WAIT 状态。
如果此时收到来自服务端的 FIN 报文是乱序的,也就是服务端发送的 FIN 报文的序列号与方才由其发送给客户端的数据的序列号不是顺序的,那么这个 FIN 报文会进入缓冲区队列。客户端再次收到之前由于网络延迟刚刚到达的数据包之后,将数据也放到缓冲区队列。当客户端不再能接收到数据时,去缓冲区队列中按顺序查看 FIN 报文的序列号是否合法,如果合法,那么就触发状态转换,从 FIN_WAIT_2 进入到 TIME_WAIT 状态并发送 ACK 报文。如果 FIN 报文的序列号不合法,则丢弃并等待合法的 FIN 报文。
TCP 的四次挥手丢了怎么办?
- 第一次丢失:客户端发送 FIN 报文,服务端没能收到,那么客户端在 FIN_WAIT_1 状态下触发超时重传。
- 第二次丢失:处于 FIN_WAIT_1 状态下的客户端没有收到服务端的 ACK 报文,由于服务端不会重发 ACK 报文,那么客户端重传 FIN 报文。
- 第三次丢失:服务端发送的 FIN 报文丢失,客户端在 FIN_WAIT_2 状态下无限等待,直到收到服务端重发的 FIN 报文。
- 第四次丢失:客户端发送的 ACK 丢失。客户端发送 ACK 后进入 TIME_WAIT 状态,此时服务端处于 LAST_ACK 状态,如果没有收到客户端的 ACK 报文,那么服务端会重发 FIN 报文。处于 TIME_WAIT 状态下的客户端在重新收到 FIN 报文时会重发 ACK 报文,并重置 2MSL 定时器。如果此时客户端已经退出,那么服务端在达到超时重传次数上限后也断开连接。
TCP 的延迟应答和累积应答?
延迟应答:TCP 在收到对端的报文后,不会立即发送 ACK 报文予以确认,而是等待一段时间后再发送 ACK,以便将 ACK 和要发送的数据一起发送。延迟的时间不能很长,否则会触发超时重传。
累积应答:为了保证顺序性,TCP 数据报为数据部分的每一个字节都赋予了一个序列号,但是报头当中的序列号保存的是数据部分第一个字节的序列号。在传输数据时,为了确保数据发送顺序以及数据可靠性,接收方会对发送方发送的数据进行确认,通过携带确认号的 ACK 报文来完成。但是确认报文不是逐字节确认,而是对某一个字节进行确认,代表该字节序列号之前的数据都已经收到了。这种模式叫做累积应答。
总结:延迟应答指的就是接收方积攒一部分数据与 ACK 报文一同发送,而不是收到发送方数据后立马发送 ACK 报文。累积应答指的就是接收方发送的 ACK 报文当中的序列号标识的是期望接收到的下一个序列号,其之前序列号对应的数据已经全部收到。
TCP 会出现三次挥手吗?
「会出现」。如果服务端在收到客户端的 FIN 报文后,没有数据要发送了,就会将 FIN 和 ACK 合并发送,这就出现了三次挥手。
TCP 的 MSL?
MSL 指的是任何报文在网络中被丢弃之前的最长存活时间。TCP 报文是被包装在 IP 数据报中传输的,IP 数据报有生存时间 TTL。