linux网络编程/TCP三次握手与四次挥手

一、三次握手

在 TCP/IP 协议中,TCP 协议提供可靠的连接服务,采用三次握手建立一个连接。
linux网络编程/TCP三次握手与四次挥手
第一次握手:建立连接时,客户端发送 syn 包到服务器,并进入 SYN_SEND 状态,等待服务器确认;

第二次握手:服务器收到 syn 包,必须确认客户的 SYN,同时自己也发送一个 SYN 包,即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态;

第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK,此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,完成三次握手。
linux网络编程/TCP三次握手与四次挥手
通过这样的三次握手,客户端与服务端建立起可靠的双工的连接,开始传送数据。 三次握手的最主要目的是保证连接是双工的,可靠更多的是通过重传机制来保证的。 TCP为什么需要进行三次握手我们可以这样理解: 为了保证服务端能收接受到客户端的信息并能做出正确的应答而进行前两次(第一次和第二次)握手,为了保证客户端能够接收到服务端的信息并能做出正确的应答而进行后两次(第二次和第三次)握手。
二、TCP连接释放机制–四次挥手
参加数据交换的双方中的任何一方(客户端或服务器)都可以关闭连接,当一个方向的连接被终止时,另一个方向仍可继续传输数据。TCP连接释放分为正常释放和非正常终止两种。
1—–TCP连接正常释放—四次挥手方式

由于 TCP 连接是全双工的,因此每个方向都必须单独进行关闭。这好比,我们打电话(全双工),正常的情况下(出于礼貌),通话的双方都要说再见后才能挂电话,保证通信双方都把话说完了才挂电话。
那TCP 的四次握手,是为了保证通信双方都关闭了连接,具体过程如下:
linux网络编程/TCP三次握手与四次挥手

1)客户端 A 发送一个 FIN,用来关闭客户 A 到服务器 B 的数据传送;
2)服务器 B 收到这个 FIN,它发回一个 ACK,确认序号为收到的序号加 1。和 SYN 一样,一个 FIN 将占用一个序号;
3)服务器 B 关闭与客户端 A 的连接,发送一个 FIN 给客户端 A;
4)客户端 A 发回 ACK 报文确认,并将确认序号设置为收到序号加 1。
1、 为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
2、 为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
这是因为:虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。