TCP介绍
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议.
TCP使用三次握手建立连接,四次握手来终止连接(由于TCP半关闭的特点).如下图:
TCP连接(三次握手)
Client发送SYN(Synchronize Sequence Numbers)消息/包,其中Sequence number 为x(随机生成),状态:SYN_SENT
Server收到Client的SYN消息,记录并回复ACK(Acknowledge character)消息(ACK = X+1),以及自己的SYN(Seq=y)消息,状态:SYN_RCVD
Client收到Server的SYN和ACK消息,确认无误后建立连接,并回复ACK消息(ACK=y+1),状态:ESTABLISHED
Server收到Client的ACK消息,确认无误,建立连接,状态:ESTABLISHED
其中之所以有第三次握手,是为了减轻服务器的负担,确保这次连接建立有效而不浪费服务器资源,否则存在服务器建立了连接而客户端并没有对应连接建立的情况或者服务器有两个连接 而客户端只有一个(网络原因发了两次连接建立请求)
TCP断开(四次握手)
Client发送FIN消息,seq = u(u为当前消息序列号,因为FIN消息也必须消耗一次序列号),状态:FIN-WAIT-1
Server收到FIN消息回复ACK消息并带上当前消息序列号,并等待其他消息发送完毕,状态:CLOSE-WAIT
Client收到ACK消息,状态:FIN-WAIT-2
Server其他消息发送完毕,发送FIN消息并带上当前序列号(因为不确定服务器到底还发送了多少消息,假定w),状态:LAST-ACK
Client收到FIN消息回复ACK消息,并进入TIME-WAIT状态
Server收到ACK消息,状态:CLOSED
实际上第一次握手和第三次握手同样携带了ACK(标志位)和ack(序列号),原因如下:
因此企业防火墙如果只允许公司内主机访问Internet,而不让Internet访问公司内主机,可以使用ACK==1过滤(拦截ACK==0的建立请求),在出口路由器的入口方向配置ACL:
1 | Permit TCP any established |
问题
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态
虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
参考
kaleidoscopic https://www.cnblogs.com/kaleidoscope/p/9701117.html
huoruilin https://blog.csdn.net/justinhuo/article/details/90744624
青柚_ https://blog.csdn.net/qq_38950316/article/details/81087809