文章目录
- 昨日内容复习
- TCP 的四次挥手?
- TCP 为什么要四次挥手?
- 在客户端处于 FIN_WAIT_2 状态时,如果此时收到了乱序的来自服务端的 FIN 报文,客户端会如何处理?何时进入 TIME_WAIT 状态?
- TCP 四次挥手丢了怎么办?
- TCP 的延迟应答和累积应答?
- TCP 会出现三次挥手吗?
- TCP 的 MSL?
- 复习计算机网络 Day3:TCP 协议的其他相关问题
- 已经建立了 TCP 连接,客户端突然出现故障了怎么办?
- 什么时候用长连接,什么时候用短连接?
- TCP 的半连接队列和全连接队列?
- 什么是 SYN 攻击?如何避免?
- TIME_WAIT 的作用?过多如何解决?
- TIME_WAIT 为什么要经过 2MSL?
- CLOSED_WAIT 过多如何解决?
昨日内容复习
TCP 的四次挥手?
TCP 的四次挥手过程可以总结如下,为了方便描述,我们将客户端认定为主动关闭方,将服务端认定为被动关闭方:
- 第一次挥手:客户端发送 FIN 置位的报文到服务端,并从 ESTABLISED 状态进入 FIN_WAIT_1 状态,此时客户端为半关闭状态,客户端仍然可以接收数据,但是不会再发送数据;
- 第二次挥手:服务端接收到客户端的 FIN 报文后,发送 ACK 报文对 FIN 报文进行确认,同时进入 CLOSED_WAIT 状态,再次期间服务端将继续处理应用层还没有发送完的数据。客户端收到 ACK 后进入 FIN_WAIT_2 状态;
- 第三次挥手:服务端处理好数据后,发送 FIN 报文,随后进入 LAST_ACK 状态;
- 第四次挥手:客户端接收到来自服务端的 FIN 报文后,进入 TIME_WAIT 状态,等待 2MSL 时间后客户端关闭。服务端收到 ACK 报文后立即关闭。
TCP 为什么要四次挥手?
TCP 进行四次挥手而不是三次挥手的原因是服务端可能在收到客户端的 FIN 后仍然有数据要发送,因此服务端确认客户端发来的 FIN 报文的 ACK 报文与服务端发送给客户端的 FIN 报文在有数据没有处理完的情况下不能合并,因此 TCP 需要四次挥手。
当然,需要注意的是,TCP 可以三次挥手,当服务端没有数据发送给客户端时,服务端将 ACK 与 FIN 合并,发送 FIN-ACK 报文。
在客户端处于 FIN_WAIT_2 状态时,如果此时收到了乱序的来自服务端的 FIN 报文,客户端会如何处理?何时进入 TIME_WAIT 状态?
如果客户端收到了乱序的来自服务端的 FIN 报文,会将其存入缓冲区,等待服务端的其他数据到达,一并放入缓冲区。当客户端接收不到数据时,按顺序比对报文的序列号,如果 FIN 报文的序列号顺序且合法,则将其视为正确的 FIN 报文,回发 ACK 报文并进入 TIME_WAIT 状态;否则丢弃 FIN 报文,等待正确的 FIN 报文。
TCP 四次挥手丢了怎么办?
- 第一次挥手丢失:客户端发送给服务端的 FIN 报文丢失,此时客户端收不到来自服务端的 ACK 报文,触发超时重传;
- 第二次挥手丢失:服务端确认客户端的 FIN 报文的 ACK 报文丢失,此时客户端会认为自己的 FIN 报文丢失,客户端触发超时重传;
- 第三次挥手丢失:客户端没有收到服务端的 FIN 报文,此时客户端处于 FIN_WAIT_2 状态,不会给服务端发送 ACK 报文,因此服务端会触发超时重传,重新发送 FIN 报文;
- 第四次挥手丢失:服务端没有收到客户端的 ACK 报文,此时服务端会重新发送 FIN 报文给客户端。客户端发送 ACK 之后进入 2MSL 的 TIME_WAIT 状态,当再次收到 FIN 报文后,会重置 2MSL 计时器,并再次发送 ACK 报文。如果客户端此时已经到达 2MSL 并关闭,那么服务端会在超时重传最大次数上限后关闭连接。
TCP 的延迟应答和累积应答?
- 延迟应答:TCP 不会立即发送 ACK 应答接收到的报文,而是积累一定的数据后,与 ACK 报文一并发送;
- 累积应答:TCP 头部当中的确认号表示的是发送报文的一方期望下一次收到的序列号,说明该序列号之前的字节已经全部收到,这就是累积应答。
TCP 会出现三次挥手吗?
会,当被动关闭方收到主动关闭方 FIN 报文后,没有数据要发送时,将 ACK 和 FIN 合并发送,此时就出现了三次挥手。
TCP 的 MSL?
指的是报文的最长生命周期,即报文在网络中被丢弃之前的最长生存时间。TCP 报文被包裹在 IP 数据报中,IP 数据报的报头有 TTL 字段。
复习计算机网络 Day3:TCP 协议的其他相关问题
已经建立了 TCP 连接,客户端突然出现故障了怎么办?
TCP 存在保活计时器,如果客户端发生故障,服务端不会一直等待。计时器通常设置为两个小时,每当客户端有消息发送过来,服务端都会重置计时器。超时之后,服务端每隔一定的时间周期(75 s)向客户端发送探测报文,如果连续十次都没有回复,服务端会认为客户端发生故障,断开连接。
什么时候用长连接,什么时候用短连接?
长连接多用于操作频繁的点对点通讯,而且连接数不能太多。例如,数据库的连接就是长连接。
Web 网站的 HTTP 服务一般使用短连接,短连接可以快速释放资源。
TCP 的半连接队列和全连接队列?
半连接队列:也称 SYN 队列。服务端收到客户端的 SYN 请求连接报文后,内核会把该连接存储到半连接队列中,并向客户端发送 SYN-ACK 报文。换句话说,半连接队列(SYN 队列)存储的就是已经向服务端发起了连接请求但是还没有完成连接建立的客户端。
全连接队列:也称 ACCEPT 队列。服务端收到第三次握手客户端发送的 ACK 报文后,内核就会把该客户端从 SYN 队列中移除,并转入到 ACCEPT 队列。
什么是 SYN 攻击?如何避免?
SYN 攻击指的是恶意攻击方通过合法手段不断向服务端发送 SYN 报文,从而使得合法用户无法得到服务响应。当大量的 SYN 请求到来时,服务端会进入 SYN_RECV 状态,将连接加入到 SYN 队列并分配进程控制块,同时回发 SYN-ACK 报文,当服务端等不到 ACK 报文时,还会不断触发超时重传重新发送 SYN-ACK 报文,最终导致服务端资源耗尽。
解决办法:
- Cache:收到 SYN 报文后使用 Hash 表保存 SYN 报文的信息,发送 SYN-ACK 后,收到 ACK 才为该连接分配 TCB,节省资源;
- Cookie:服务端收到 SYN 报文后,不直接分配资源,而是通过加密算法生成一个 SYN Cookie 作为初始序列号。只有收到客户端发送的合法的 ACK 后才分配连接资源。
- Proxy 防火墙:设立中间层防火墙,确认连接有效后,才向内部服务器发送 SYN 请求。
- 减少 SYN-ACK 重传次数;
- 监视半连接队列和全连接队列当中的无效连接;
- 增大半连接队列的数量;
TIME_WAIT 的作用?过多如何解决?
TCP 常用的三种状态:ESTABLISHED 表示连接建立,CLOSED_WAIT 表示被动关闭,TIME_WAIT 表示主动关闭。
TIME_WAIT 的作用
- 确保主动关闭方发送的最后一个 ACK 到达被动关闭方:主动关闭方在接收到 FIN 报文后,发送 ACK 予以确认,并进入 2MSL 的 TIME_WAIT 状态。如果这个 ACK 丢失,那么被动关闭方会重发 FIN,主动关闭方收到后会重发 ACK。如果没有 TIME_WAIT,那么被动关闭方在没有收到 ACK 之后,会不断触发超时重传重新发送 FIN 报文,导致资源的消耗。
- 避免旧连接的延迟报文干扰新的连接:TCP 连接通过四元组唯一标识。如果旧的连接中存在由于网络阻塞而没有到达对端的报文,则接收方会误认为这些报文是新的连接发送的,导致数据错乱。旧的连接等待 2MSL 再关闭可以确保旧的报文在网络中全部消亡;
- 确保全双工通道的可靠关闭:TCP 是全双工协议,双方都需要关闭自己的连接。TIME_WAIT 可以确保双方都能完成关闭流程,即使主动关闭方发送给被动关闭方的 ACK 丢失,由于主动方处于 TIME_WAIT,仍然可以接收 FIN 并重发 ACK。
TIME_WAIT 的副作用
过多的 TIME_WAIT 会占用端口和内存资源(高并发短连接场景下),导致新的连接无法建立。
解决办法:
- 快速回收 TIME_WAIT;
- 调整 MSL 时间;
- 负载均衡或连接池:复用长连接以减少短连接数量。
TIME_WAIT 为什么要经过 2MSL?
第一个 MSL:确保主动关闭方的 ACK 到达对端;
第二个 MSL:确保对端重传的 FIN 可以到达本端;
CLOSED_WAIT 过多如何解决?
CLOSED_WAIT 过多代表被动关闭方为能正确地关闭连接,导致连接资源长期占用。可能是由于程序 Bug 及配置问题导致的,应该去检查程序。