三次握手及四次挥手图示
[图片从网上找的,有问题的地方用红色标记了]
各种状态如下
- CLOSED :初始状态,表示没有任何连接。
- LISTEN : Server 端的某个 Socket 正在监听来自远方的 TCP 端口的连接请求。
- SYN_SENT :发送连接请求后等待确认信息。当客户端 Socket 进行 Connect 连接时,会首先发送 SYN(Synchronized Bit)(同步序号,用于发起一个连接) 包,随即进入 SYN_SENT 状态,然后等待 Server 端发送三次握手中的第 2 个包。
- SYN_RECEIVED :收到一个连接请求后回送确认信息和对等的连接请求,然后等待确认信息。通常是建立 TCP 连接的三次握手过程中的一个中间状态,表示 Server 端的 Socket 接收到来自 Client 的 SYN 包,并作出回应。
- ESTABLISHED :表示连接已经建立,可以进行数据传输。
- FIN_WAIT_1 :主动关闭连接的一方等待对方返回 ACK(Acknowledgment Bit)(值为1,确认序号生效) 包。若 Socket 在 ESTABLISHED 状态下主动关闭连接并向对方发送 FIN (Finish Bit)(发送端要求关闭连接)包(表示己方不再有数据需要发送),则进入 FIN_WAIT_1 状态,等待对方返回 ACK 包,此后还能读取数据,但不能发送数据。在正常情况下,无论对方处于何种状态,都应该马上返回 ACK 包,所以 FIN_WAIT_1 状态一般很难见到。
- FIN_WAIT_2 :主动关闭连接的一方收到对方返回的 ACK 包后,等待对方发送 FIN 包。处于 FIN_WAIT_1 状态下的 Socket 收到了对方返回的 ACK 包后,便进入 FIN_WAIT_2 状态。由于 FIN_WAIT_2 状态下的 Socket 需要等待对方发送的 FIN 包,所有常常可以看到。若在 FIN_WAIT_1 状态下收到对方发送的同时带有 FIN 和 ACK 的包时,则直接进入 TIME_WAIT 状态,无须经过 FIN_WAIT_2 状态。
- TIME_WAIT :主动关闭连接的一方收到对方发送的 FIN 包后返回 ACK 包(表示对方也不再有数据需要发送,此后不能再读取或发送数据),然后等待足够长的时间( 2MSL )以确保对方接收到 ACK 包(考虑到丢失 ACK 包的可能和迷路重复数据包的影响),最后回到 CLOSED 状态,释放网络资源。
- CLOSE_WAIT :表示被动关闭连接的一方在等待关闭连接。当收到对方发送的 FIN 包后(表示对方不再有数据需要发送),相应的返回 ACK 包,然后进入 CLOSE_WAIT 状态。在该状态下,若己方还有数据未发送,则可以继续向对方进行发送,但不能再读取数据,直到数据发送完毕。
- LAST_ACK :被动关闭连接的一方在 CLOSE_WAIT 状态下完成数据的发送后便可向对方发送 FIN 包(表示己方不再有数据需要发送),然后等待对方返回 ACK 包。收到 ACK 包后便回到 CLOSED 状态,释放网络资源。
- CLOSING :比较罕见的例外状态。正常情况下,发送 FIN 包后应该先收到(或同时收到)对方的 ACK 包,再收到对方的 FIN 包,而 CLOSING 状态表示发送 FIN 包后并没有收到对方的 ACK 包,却已收到了对方的 FIN 包。有两种情况可能导致这种状态:其一,如果双方几乎在同时关闭连接,那么就可能出现双方同时发送 FIN 包的情况;其二,如果 ACK 包丢失而对方的 FIN 包很快发出,也会出现 FIN 先于 ACK 到达。
- 另外还有三个标志位其中没有提到:
URG(Urgent Bit)值为1时,紧急指针生效
PSH(Push Bit)接收方应尽快将这个报文段交给应用层
RST(Reset Bit)发送端遇到问题,想要重建连接
为什么要有三次挥手和四次握手?
1、为什么需要三次握手
目的:为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。主要防止资源的浪费。
具体过程:
当客户端发出第一个连接请求报文段时并没有丢失,而是在某个网络节点出现了长时间的滞留,以至于延误了连接请求在某个时间之后才到达服务器。这应该是一个早已失效的报文段。但是服务器在收到此失效的连接请求报文段后,以为是客户端的一个新请求,于是就想客户端发出了确认报文段,同意建立连接。假设不采用三次握手,那么只要服务器发出确认后,新的连接就可以建立了。但是由于客户端没有发出建立连接的请求,因此不会管服务器的确认,也不会向服务器发送数据,但服务器却以为新的运输连接已经建立,一直在等待,所以,服务器的资源就白白浪费掉了。
1.1、如果在TCP第三次握手中的报文段丢失了会出现什么情况?
客户端会认为此连接已建立,如果客户端向服务器发送数据,服务器将以RST包响应,这样就能感知到服务器的错误了。
2、为什么要四次挥手
为了保证在最后断开的时候,客户端能够发送最后一个ACK报文段能够被服务器接收到。如果客户端在收到服务器给它的断开连接的请求之后,回应完服务器就直接断开连接的话,若服务器没有收到回应就无法进入CLOSE状态,所以客户端要等待两个最长报文段寿命的时间,以便于服务器没有收到请求之后重新发送请求。
防止“已失效的连接请求报文”出现在连接中,在释放连接的过程中会有一些无效的滞留报文,这些报文在经过2MSL的时间内就可以发送到目的地,不会滞留在网络中。这样就可以避免在下一个连接中出现上一个连接的滞留报文了。
博文参考链接:
【1】为什么有三次握手和四次挥手?
【2】牛客网-一条tcp连接,主动关闭的一方不可能出现的连接状态是()讨论总结