备忘录1.TCP的三次握手与四次挥手过程

三次握手与四次挥手是指TCP连接建立与释放的过程。为了弄清楚三次握手和四次挥手,需要先简单了解什么是TCP协议,TCP协议的特点以及TCP传送的数据单元。

一、什么是TCP协议

TCP,Transmission Control Protocol,中文名为传输控制协议。它属于传输层通信协议,是为了在不可靠的IP层上实现可靠传输的数据传输协议。网络层虽然可以实现两个主机之间的通信,但真正进行通信的实体是在主机的进程中,而传输层位于网络层之上,是它为运行在不同主机的进程之间提供了逻辑通信。传输层提供两种不同的传输协议,即面向连接的TCP协议和无连接的UDP协议。

二、TCP协议的特点

1)面向连接。

2)每个TCP连接只能有两个端点,即一对一。

3)TCP提供可靠的交付服务,保证传送的数据无差错、不丢失、不重复且有序。

4)TCP提供全双工通信,即允许通信双方的应用进程在任何时候都能发送数据。

5)面向字节流,TCP把交付数据仅看作一连串无结构的字节流。

三、TCP报文段

TCP传送的数据单元称为报文段,一个TCP报文段由首部和数据部分两个部分组成。TCP报文段既可以用来运载数据,也可以用来建立连接、释放连接和应答。

其中几个和连接相关的重要字段:

1)序号字段:用来给TCP连接中传送的数据流编号。由于TCP是面向字节流的,故规定序号字段的值指的是该报文段所发送的数据的第一个字节的编号。

2)确认号字段:用来表示已确认收到的数据。规定其值含义为期望收到对方的下一个报文段的数据部分的第一个字节的编号。比如确认号为N,表示到序号N-1为止的所有数据都已正确收到。

3)确认位ACK:ACK=1表示这是对对方发送的报文段的确认报文段。

4)同步位SYN:同步位SYN=1表示这是一个连接请求或连接接收报文段。

5)终止位FIN:FIN=1表示已发送完毕的一方要释放连接。

四、三次握手过程

首先,说明一下TCP两端连接建立过程中的几种状态:

1)CLOSED:表示初始状态。

2)LISTEN:表示服务器端的某个SOCKET处于监听状态,可以接受连接了。

3)SYN_SENT:当客户端SOCKET执行CONNECT连接时,它首先发送SYN报文,因此也随即它会进入到了SYN_SENT状态,并等待服务端的发送三次握手中的第2个报文。

4)SYN_RCVD:表示收到了SYN报文,这种状态时,当收到客户端的ACK报文后会进入到ESTABLISHED状态。在正常情况下,这个状态很短暂,基本上用netstat是很难看到的,除非特意写一个客户端测试程序,故意将三次握手中最后一个ACK报文不予发送。

5)ESTABLISHED:表示连接已经建立了。

第一步:客户机的TCP(指TCP传输实体)向服务器的TCP发送一个连接请求报文段。其首部中SYN=1(表示这是一个连接请求报文段)。另外,客户机会选择一个起始序号seq=x,SYN报文不携带应用层传下来的数据,但要消耗掉一个序号。此时,客户端从CLOSED状态进入SYN_SENT状态。

第二步:服务器的TCP收到连接请求报文段后,如果同意连接,就向客户机发回确认,并为该TCP连接分配TCP缓存和变量。在该确认报文段中,SYN=1,ACK=1(表示这是一个连接接收报文段),且ack=x+1,服务器产生起始序号seq=y。同样,该报文不携带应用层传下来的数据,但也要消耗掉一个序号。此时,服务器端从LISTEN状态进入SYN_RCVD状态。

【注】因为TCP是全双工通信,所以TCP连接的两端都各自设有发送缓存和接收缓存。发送缓存用来暂时存放以下数据:(1)发送应用程序传送给发送方TCP准备发送的数据;(2)TCP已发送但尚未收到确认的数据。接收缓存用来暂时存放以下数据:(1)按序到达的但尚未被接受应用程序读取的数据;(2)不按序到达的数据。

第三步:当客户机收到服务器的确认报文段后,还要再次向服务器给出确认,并且给该连接分配缓存和变量。这个报文段的ACK=1,SYN=0(只有前两次握手才需要SYN=1),seq=x+1,ack=y+1。此报文段可以携带数据了,如果不携带数据则不消耗序号。此时,客户端和服务器端进入ESTABLISHED状态,连接建立完成。

五、四次挥手过程

四次挥手指TCP连接释放的过程,由于TCP是全双工通信,可以理解为一个TCP连接上有两条数据通路,所以需要TCP连接两段分别断开每一条数据通路。

TCP两端连接释放的几种状态:

1)FIN_WAIT_1:当客户端在ESTABLISHED状态想主动关闭连接时,向对方发送FIN报文即进入到FIN_WAIT_1状态。等对方回应ACK报文后,则进入到FIN_WAIT_2状态。在实际正常情况下,无论对方何种情况,都应该马上回应ACK报文,故FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。

2)FIN_WAIT_2:表示半连接,也就是只关闭了其中一条数据通路。

3)TIME_WAIT:表示收到了对方的FIN报文并发送出了ACK报文,只等2MSL后即可回到CLOSED状态了。如果在FIN_WAIT_1状态下收到了对方同时带FIN标志和ACK标志的报文,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。

4)CLOSING:表示客户端发送FIN报文后,并没有收到对方的ACK报文,反而收到对方的FIN报文,也就是通信双方都正在关闭SOCKET连接。这种状态实际情况中很罕见。

5)CLOSE_WAIT:当收到对方发送的FIN报文并回应一个ACK报文时则进入到CLOSE_WAIT状态。在CLOSE_WAIT状态下,考虑自己是否还有数据要发送。

6)LAST_ACK:表示被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。

第一步:当客户端数据发送完成准备关闭连接时,就向其TCP传输实体发送一个连接释放报文段,主动关闭TCP连接,该报文段FIN=1,seq=u(前面已传送的数据的最后的一个字节的序号加1),和SYN报文段一样,FIN报文段即使不携带数据,也要消耗掉一个序号,其实应该还有一个ack=v(图上没标,因为不是重点)。当一端发送FIN报文时,它就不能再发送数据,相当于这关闭了其中一条数据通路,而另一端可以继续发送数据。此时,客户端进入FIN-WAIT-1状态。

第二步:服务器收到连接释放报文段后即发出确认,ack=u+1,seq=v,等于它前面已传送过的数据的最后一个字节的序号加1。此时,从客户机到服务器这个方向的连接就算释放了,TCP连接处于半关闭状态。但从服务器到客户机这个方向的数据通路并未关闭。此时,服务端就进入了CLOSE-WAIT状态,而当客户端收到了服务器端的确认报文段后即进入FIN-WAIT-2状态。

第三步:若服务器发送完毕,就通知TCP释放连接,此时发出FIN=1的连接释放报文段。ACK=1,ack=u+1,seq=w。此时,服务器就进入了LAST-ACK状态。

第四步:客户机收到连接释放报文段后,必须发出确认。此时,客户端就进入了TIME-WAIT状态。在确认报文段中,ACK=1,ack=w+1,seq=u+1。但这时TCP连接还没释放掉,必须经过时间等待计时器设置的时间2MSL后,客户端和服务器端都进入CLOSED状态。

六、相关问题

1)为什么不能用两次握手进行TCP连接?

答:主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。在采取两次握手的情况下,假设客户端发送了第一个请求连接并且没有丢失,只是在网络结点中滞留的时间太长了,由于客户端迟迟没有收到确认报文,以为服务器没有收到,便重新向服务器发送连接请求报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。但之前滞留的那条连接请求报文,又网络通畅了,到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。如果采用的是三次握手,当之前失效的连接请求报文传送过来时,就算服务器端回复了确认报文,但是客户端不会再次发出确认,就不会建立连接。

2)为什么连接的时候是三次握手,关闭的时候却是四次挥手?

答:连接时,当服务器端收到客户端的SYN报文后,可以直接发送SYN+ACK报文,也就是应答加上同步。但是关闭连接时,当服务器端收到FIN报文时,很可能还要继续向客户端发送数据,所以只能先回复一个ACK报文。只有服务器端所有的报文都发送完了,才能向客户端发送FIN报文,因此不能一起发送。故需要四次挥手。

3)为什么TIME_WAIT状态需要经过2MSL(Maximum Segment Lifetime,最大报文段生存时间)才能返回到CLOSE状态?

答:为了保证最后一个ACK能够顺利到达。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果不等待2MSL,且最后一个ACK丢失,则服务器端不能进入正常关闭状态,造成错误。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。如果Server没有收到ACK,将不断重复发送FIN报文段。Client在发送出ACK之后进入到TIME_WAIT状态并且设置一个计时器,等待2MSL的时间。如果在2MSL时间内再次收到FIN,说明最后一个ACK丢失,那么Client会重发ACK并再次等待2MSL。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则成功结束TCP连接。(服务器结束TCP连接的时间要比客户端早一些,因为客户端最后要等待2MSL后才可以进入CLOSED状态。)

4)如果已经建立了连接,但是客户端突然出现故障了怎么办?

答:TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

4)为什么TCP在建立连接时不能每次都选择相同的、固定的初始序号?

答:假定每一次建立连接时,主机A都选择相同的、固定的初始序号,比如1。假设主机A和B频繁地建立连接,且A发送的某些TCP报文段会在网络中滞留较长的时间,以造成A超时重传这些报文段。而有一些在网络中滞留时间较长的报文段最后终于到达了主机B,但这时传送该报文段的那个连接早已释放了。这样,工作在新的TCP连接中的主机B就有可能会接收在旧的连接中的、已经没有意义的、过时的报文段,结果产生错误。

参考文档:

(1)《王道2019年计算机网络考研复习指导》;

(2)TCP三次握手原理,以及为什么不能改成两次握手 - 若水弹丸之地 - CSDN博客https://blog.csdn.net/b954960630/article/details/81861579;

你可能感兴趣的:(备忘录1.TCP的三次握手与四次挥手过程)