三次挥手
为什么建立连接需要三次握手?
三次握手的目的:为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误,保证在信道上传输可靠的数据
第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(建立)状态,完成三次握手。握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。
假设有这样一次场景:客户端(A) 服务端(B)
客户端A发出去的第一个连接请求报文并没有丢失,而是因为某些未知的原因在某个网络节点上发生滞留,导致延迟到连接释放以后的某个时间才到达服务端B,但是服务端B收到此失效的报文之后,会误认为是客户端A再次发出的一个新的连接请求,于是B就向A又发出确认报文,表示同意建立连接。
如果此时没有三次握手,那么只要B端发出确认报文就会认为新的连接已经建立了,但是A端并没有发出建立连接的请求,因此不会去向B端发送数据,B端没有收到数据就会一直等待。这样B端就会白白浪费掉很多资源
如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。
从以上流程可以看到,3次握手,是可以让通信双方确认连接有效,以进行正常全双工通信认知的最少“握手”次数。所以TCP选择了3次握手~
四次挥手
为什么断开连接需要四次挥手?
四次挥手的目的:因为TCP是一个全双工协议,必须单独拆除每一条信道。4次挥手的目的是终止数据传输,保证数据传输完成,并回收资源。
第一步,客户端主动发起一个请求给服务端,里面包含FIN标识位=1,客户端的seq序列号u,表示的是当前客户端在该连接上的当前序列号。
第二步,服务端在收到这个含有FIN的请求消息之后,校验无误之后会立马回复ACK消息给客户端,消息内部包含ACK标志位为1,同时seq号码是FIN的请求消息的seq号+1。此时的服务端同时会主动发个结束标识给服务端上面的应用层程序,应用层程序可以决定是立马结束,还是等到该连接中的数据处理完了之后,在发送FIN消息给客户端来关掉另外的一半连接。
第三步,服务端在处理完该连接上面的Pending住的数据之后,应用程序会close这个连接。服务端会主动发起FIN的消息给客户端。消息内部带有,FIN=1的结束符标识位,以及服务端的seq序列号。
第四步,客户端在收到对应的FIN消息之后,会主动通知应用层程序,告知这个连接现在需要关闭了。然后,客户端会回复ACK消息给服务端,以便断开另外一个方向的通道,这个消息包含ACK=1的标识位和FIN的请求带过来的seq+1。
假设有这样一次场景:客户端(A) 服务端(B)
客户端和服务端通过3次握手建立连接,此时客户端数据全部发送完成,需要断开连接,客户端就会向服务端发送断开请求。
服务器收到对方的客户端发送关闭报文时,仅仅表示客户端不再发送数据了但是还能接收数据,而服务器也未必全部数据都发送给客服端了,所以服务器可以立即关闭,也可以继续发送数据给客户端,如果有数据未发送完毕,就需要通知客户端,我还有数据未发送完,不要断开连接。等全部数据传输完成服务端在发送断开请求。客服端收到服务端断开报文后,重新发送一个断开确认报文,服务端收到断开报文后便断开连接。
这样便保证了数据传输完成,资源回收~
错误之处,望指正~