TCP的三次握手和四次断开实际上就是TCP通信的连接和断开。
1.三次握手
第1次握手:客户端主机A发送一个带有SYN(synchronize)标志的数据包给服务端;
第2次握手:服务端接收成功后,回传一个带有SYN/ACK标志的数据包传递确认信息,表示我收到了;
第3次握手:客户端再回传一个带有ACK标志的数据包,表示我知道了,握手结束。
其中:SYN标志位数置1,表示建立TCP连接;ACK标志表示验证字段。
三次握手的作用
1.确认双方的接受能力,发送能力是否正常
2.指定自己的初始化序列号,为后面的可靠传送做准备
3.如果是HTTPS协议的话,三次握手这个过程还会进行数字证书的验证以及加密密钥的生成
为什么需要三次握手而不是两次握手
为了防止因为已失效的请求报文突然又传到服务器引起错位。
如果采用两次握手进行连接,客户端向服务端发送syn包来请求连接,因为某些未知原因,并未到达服务器,在中间某个网络节点产生了滞留。为了建立连接,客户端会重发syn包,这次的数据包正常送达。服务端回复syn+ack之后建立了连接,但是第一包数据阻塞了的网络节点突然恢复,第一包syn包又送达到服务端,这时服务端会误认为是客户端又发起了一个新的连接,从而在两次握手之后进入等待数据状态。服务端认为是两个连接,而客户端认为是一个连接,造成了状态不一致。如果在三次握手情况下,服务端收不到最后的ack包,自然不会认为连接建立成功。
所以三次握手的本质上来说,就是为了解决网络信道不可靠的问题,为了在不可靠的信道上建立可靠的连接。
2.四次断开
建立一个连接需要三次握手,而终止一个连接要经过四次断开(也有将四次断开叫做四次挥手的)。这由TCP的半关闭(half-close)造成的。所谓的半关闭,其实就是TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。
TCP 连接的拆除需要发送四个包,因此称为四次断开,客户端或服务端均可主动发起挥手动作。
刚开始双方都处于ESTABLISHED 状态,假如是客户端先发起关闭请求。四次断开的过程如下
第一次断开:客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于 FIN_WAIT1 状态。
即发出连接释放报文段(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN_WAIT1(终止等待1)状态,等待服务端的确认。
第二次断开:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT 状态。
即服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),服务端进入CLOSE_WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT2(终止等待2)状态,等待服务端发出的连接释放报文段。
第三次断开:如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态。
即服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),服务端进入LAST_ACK(最后确认)状态,等待客户端的确认。
第四次断开:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 +1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT 状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态,服务端收到 ACK 报文之后,就处于关闭连接了,处于 CLOSED 状态。
即客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME_WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。
TCP和UDP的区别
TCP和UDP都工作在传输层,他们的目标都是在程序之间传输数据。
区别是TCP基于连接,而UDP基于非连接。举例来说就是,如果把人与人的通信比喻成进程与进程的通信,我们基本有写信和打电话两种方式。不考虑速度因素,两者最大的区别是:写信寄出去后对方是否可以收到,内容是否完整,如果多封信顺序又是否正确...这些都是未知的。而打电话则不同,从拨打电话到对方接通,互相通话再到结束通话后挂断都能得到及时的反馈,并且能确认对方准确的接收到。打电话是基于连接的也就是TCP,写信是基于非连接的也就是UDP。