TCP是一种可靠的、面向连接的协议,用于实现可靠的数据传输。它通过确认机制、重传机制和流量控制机制等机制来保证数据的可靠传输。
那么TCP连接的销毁,为何是四次挥手,而不是三次挥手呢?今天我们一起聊一聊。
为何不使用三次挥手
我们来看看,采用如下的方式,进行三次挥手操作:
我们知道TCP握手是三次,那么挥手为何不采用三次的方式呢。
看上图,我们按照服务端ACK和FIN合并一起发送至客户端的方式,即在服务端收到客户端的FIN请求后,服务端一次性发起数据请求,确认客户端的FIN请求已收到,同时向客户端发起FIN请求。
此时,若服务端仍存在数据需要发送至客户端,因服务端已准备关联,不能再发数据,所以数据是无法发到客户端的。
例如:服务端需要给客户端的数据有三部分:A部分、B部分、C部分,在A部分和B部分发到客户端后,C部分还未发送,收到了客户端的FIN请求,服务端回复了客户端ACK确认和FIN请求,那么C部分的数据,是无法发送至客户端的,此时,客户端仅收到了A部分和B部分的数据,收到的数据不完整。
可见,直接采用三次挥手的方式,是存在明显的问题的。
四次挥手
先看看四次挥手的图示:
发起方:主动发起链路关闭的一方,一般为客户端,但也可能为服务端,上图是以客户端为发起方举例。
接收方:被动接受链路关闭的一方,一般为服务端,但也可能为客户端,上图接收方为服务端举例。
第一次挥手:发起方发起链路关闭请求,seq=a,代表发起方使用的请求序号为a,FIN请求发送后,发起方不能再发送数据到接收方,此时发起方状态变为FIN-WAIT1。
第二次挥手:接收方在收到发起方的第一次挥手后,向发起方发起第二次挥手操作,seq=b,代表接收方使用的请求序号为b;ack=a+1,即值为发起方请求序号+1。接收方发送第二次挥手后,状态变为CLOSE-WAIT状态,此时接收方仍可以发送数据到发起方。发起方在收到第二次挥手后,状态变为FIN-WAIT2。
第三次挥手:接收方等待一定的时长,一般最大时间TCP_DELACK_MAX=200MS,最短时间TCP_DELACK_MIN=40MS,具体时间根据何时有数据需发送而定。延时确认结束后,接收方向发起方发起第三次挥手,seq=b,代表接收方使用的请求需要序号为b;ack=b+1,即值为发起方请求序号+1。接收方在发起第三次挥手后,状态变为LASK-ACK。
第四次挥手:发起方在收到接收方的第三次挥手后,向接收方发起第四次挥手,seq=a+1,代表发起方使用的请求序号为a+1,即第一次发起挥手序号+1;ack=b+1,接收方第三次挥手的请求序号为b,所以确认时值为b+1。发起方发送完ACK请求后,状态变为TIME-WAIT,在等待两个MSL的时间后,状态再变为CLOSE。接收方在收到发起方的第四次挥手后,状态变为CLOSE。
ESTABLISHED状态:链路是正常的,可以发送数据和接收数据。发起方和接收方均有这个状态。
CLOSE状态:链路已关闭,原来占用的端口,可以被回收,重新使用。发起方和接收方均有这个状态。
发起方的三个专属状态:
FIN-WAIT1状态:发起方发送FIN请求后的状态,此时,发起方不能再向接收方发送数据。
FIN-WAIT2状态:发起方在收到接收方第二次挥手后的状态。
TIME-WAIT状态:发起方发起第四次挥手后的状态。接收方两个专属状态:
CLOSE-WAIT状态:接收方在收到发起方的第一次挥手,即接收到FIN请求后的状态。
LAST-ACK状态:接收方在发起第三次挥手,即发起FIN请求后的状态。另外还有个状态:
CLOSING状态:CLOSE之前的状态,时间较短,很难看到。此状态有种特殊的场景下会出现,即客户端和服务端同时发起第一次挥手操作的情况下,两边均进入FIN-WAIT1状态,期待接收到对方的ACK包,进入FIN-WAIT2状态,但却先接收到了对方的FIN包,这时就会进入CLOSING状态,然后给对方一个ACK,在收到对方的ACK包后,直接进入CLOSE状态。
四次挥手抓包
TCP延时处理机制
tcp存在延时确认机制,默认情况下,是开启的。
在使用没有带数据的ACK包时,网络效率是很低的,因为只有TCP的报文头20个字节和IP数据报的20个字节,没有携带数据报文。
为了解决网络效率低的问题,就有了TCK延时确认机制。
TCP的延时确认策略:
- 当有响应数据要发送时,ACK会随着响应数据一起立刻发送给对方。
- 当没有响应数据要发送时,ACK会延时一段时间,以等待是否有响应数据要一起发送。
- 当在延时等待发送ACK期间,对方第二个数据报文又到了,这时就会立刻马上发送ACK。
TCP延时确认机制的优点:
- 减少不必要的确认包:通过延迟发送确认包,TCP可以合并多个数据包到一个确认包中,减少了网络中不必要的确认包数量,降低了网络拥塞。
- 提高网络传输效率:通过减少不必要的确认包,TCP延迟确认机制提高了网络传输的效率,降低了网络延迟,提高了应用程序的性能。
- 自动适应网络环境:TCP延迟确认机制能够根据网络环境的变化自动调整延迟时间,适应不同的网络环境和数据传输需求。
TCP延时确认机制的缺点:
- 可能会增加延迟:由于延迟确认机制的存在,接收端可能会延迟发送确认包,从而导致应用程序的响应时间增加。对于对延迟要求较高或实时性要求较高的应用程序,TCP的延迟确认机制可能不太适用。
- 不适合所有场景:TCP的延迟确认机制适用于数据量较大、数据传输速率较慢或网络环境较差的场景。对于数据量较小、数据传输速率较快或网络环境较好的场景,该机制可能不太适用。
- 需要合理配置:TCP的延迟确认机制需要合理配置延迟时间,如果延迟时间设置过长或过短,可能会影响网络传输性能。
TCP的延迟确认机制是一种有效的优化技术,可以显著提高网络传输的效率和性能。但在实际应用中,需要根据具体场景和需求进行合理配置和使用。
现实中看到的三次挥手
现实场景中,是否会存在三次挥手的情况呢?我们假定一种场景:
- 使用了TCP的延时确认机制
- 没有要发送的数据
在发起方发起第一次挥手后,接收方存在以上的场景,接收方准备发起ACK请求(第二次挥手),在接收方开启了TCP延时确认机制下,接收方等待了200MS,仍没有数据要发送,此时原接收方第三次挥手的FIN请求,会和ACK请求合并后,一次性发送至接收方。
在实际应用中,是否会存在直接使用一次挥手,直接关闭链接呢?
如客户端在正确接收服务端的响应后,直接发送RST,ACK的挥手请求?
遇到这种情况,是否属于存在问题?又应当如何应对呢?
欢迎私信或留言讨论。