传输层 TCP连接管理 释放连接四次握手_数据

传输层 TCP连接管理 释放连接四次握手_数据_02

A计算机传输完了数据,传完之后要发出释放连接的数据包,这个TCP的FIN标记位为1,序号为u,B收到之后就通知应用程序A发完了,A不给B发了,B收到之后给它发送确认,确认号是u+1,序号是v,确认标记位为1。

在发送了关闭连接的请求之后,A状态就变为了FIN-WAIT-1,B发送确认之后变为CLOSE-WAIT,变成了关闭并且等待。现在A不能向B发送数据的,但是B可以向A发送数据,B发送释放连接的请求,这个时候FIN标记位为1,确认号还是u+1,然后序号是w,A收到并且确认号是w+1。然后B就close了,关闭连接了。

关闭连接之后还得等一段时间,time-wait,这个时间时间是几分钟,为啥还要等,是因为万一这个包在路上丢了怎么办?如果丢了,还需要再发一遍释放连接的请求,所以这边还需要等一段时间。如果发送释放连接的请求,如果没有time-wait等待了,那么A就搭理B了。

释放连接需要4个数据包。

-----------------------------------------------------------------------------------------------------------------------------

第一次挥手:A 的应用进程先向其 TCP 发出连接释放报文段,并停止再发送​​数据​​​,主动关闭 TCP 连接。A 把连接释放报文段首部的终止控制位 FIN 置 1,其序号 seq = u(等于前面已传送过的​​数据​​​的最后一个字节的序号加 1),这时 A 进入 FIN-WAIT-1(终止等待1)状态,等待 B 的确认。请注意:TCP 规定,FIN 报文段即使不携带​​数据​​​,也将消耗掉一个序号。

第二次挥手:B 收到连接释放报文段后立即发出确认,确认号是 ack = u + 1,而这个报文段自己的序号是 v(等于 B 前面已经传送过的​​​数据​​​的最后一个字节的序号加1),然后 B 就进入 CLOSE-WAIT(关闭等待)状态。TCP 服务端进程这时应通知高层应用进程,因而从 A 到 B 这个方向的连接就释放了,这时的 TCP 连接处于半关闭(half-close)状态,即 A 已经没有​​数据​​​要发送了,但 B 若发送​​数据​​​,A 仍要接收。也就是说,从 B 到 A 这个方向的连接并未关闭,这个状态可能会持续一段时间。A 收到来自 B 的确认后,就进入 FIN-WAIT-2(终止等待2)状态,等待 B 发出的连接释放报文段。

第三次挥手:若 B 已经没有要向 A 发送的​​​数据​​​,其应用进程就通知 TCP 释放连接。这时 B 发出的连接释放报文段必须使 FIN = 1。假定 B 的序号为 w(在半关闭状态,B 可能又发送了一些​​数据​​​)。B 还必须重复上次已发送过的确认号 ack = u + 1。这时 B 就进入 LAST-ACK(最后确认)状态,等待 A 的确认。

第四次挥手:A 在收到 B 的连接释放报文后,必须对此发出确认。在确认报文段中把 ACK 置 1,确认号 ack = w + 1,而自己的序号 seq = u + 1(前面发送的 FIN 报文段要消耗一个序号)。然后进入 TIME-WAIT(时间等待) 状态。请注意,现在 TCP 连接还没有释放掉。必须经过时间等待计时器设置的时间 2MSL(MSL:最长报文段寿命)后,A 才能进入到 CLOSED 状态,然后撤销传输控制块,结束这次 TCP 连接。当然如果 B 一收到 A 的确认就进入 CLOSED 状态,然后撤销传输控制块。所以在释放连接时,B 结束 TCP 连接的时间要早于 A。


CLOSE-WAIT和TIME-WAIT存在的意义?


- Close-wait存在的意义: 就是服务端还有​​数据​​​要发送,这个时间内就是服务端发送完最后的​​数据​​​ - Time-wait存在的意义:
    - 第一,这里同样是要考虑丢包的问题,如果第四次挥手的报文丢失,服务端没收到确认ack报文就会重发第三次挥手的报文,这样报文一去一回最长时间就是2MSL,所以需要等这么长时间来确认服务端确实已经收到了
    - 第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。
 

 


关闭连接:防止数据丢失;与应用层交互


• FIN:结束

• ACK:确认


传输层 TCP连接管理 释放连接四次握手_网络_03

关闭连接是有两个目的,第一,必须防止数据丢失,第二我们与应用层是有交互的。

首先client和server都是处于establish的状态,由我们的client首先发起关闭连接,它是主动关闭连接的一方,首先它会发送报文,报文当中flag标志位中的FIN标志位1,发送完FIN以后,它就进入到FIN-WAIT-1状态,可以通过netstat端口的状态进入了FIN-WIAT-1,服务器接收到FIN以后,在操作系统的内核层会自动的回一个ACK,此时server端netstat就可以看到CLOSE-WAIT的状态,而server端发送来的ACK在client接受之后自动会从FIN-WAIT-1进入到FIN-WAIT-2状态,要注意到无论是FIN还是ACK都依然符合前面所说的重发确认等流程。

当server端进入到CLOSE-WAIT状态之后,如果server上面的app,它没有去处理这样一个事件,这样连接的状态永远都在CLOSE-WAIT状态。

当有些web应用出现bug的时候,那么就可以使用netstat就可以观察到CLOSE-WIAT状态。

当APP通过read函数接收到0的时候,他就知道应该去关闭这个连接了,当它调用了close的socket之后,我们的server就会发一个FIN包给到client,当server发完FIN包之后,server状态就会进入到LAST-ACK,而这个FIN包到达主动关闭连接的client端之后,这个时候在client端就会进入TIME-WAIT阶段,这在服务器经常可以看到的一个状态,这是服务器主动在关闭连接。

当主动关闭连接的client收到FIN之后就会回一个ACK,会ACK,server收到ACK之后就会进入close状态,而client发送完ACK之后,它要等两个MSL的时间,也就是TCP报文段在整个网络当中那个存活的最长时间,TIME-WAIT经过两个MSL的时间也会进入close的状态。

在456这个报文当中由172.11发起了关闭连接,在FIN控制位标记为1,说明是在关闭连接,此时172.11在关闭连接就会进入FIN-WAIT1状态,

传输层 TCP连接管理 释放连接四次握手_连接释放_04

等待浏览器去调用close socket方法,ACK到达172.11之后就会进入FIN-WAIT-2状态。

当浏览器执行了close socket之后,就由close-wait变为last-ack状态。

当fin到达172.11之后,他就会从fin-wait2变为time-wait状态,它同时发送最后一个ack,65.15收到ack之后就会从last-ack置为close的状态。