TCP的三次握手和四次挥手
三次握手 三次握手其实就是建立一个TCP连接时,需要客户端和服务器总共发送3个包,确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备。
ACK:确认序号有效;SYN:发起一个新连接。 刚开始客户端处于Closed的状态,服务器处于Listen状态。
- 第一次握手:首先客户端向服务器发送一段TCP报文,其中:标记位SYN表示请求建立新连接;序号seq=X,X一般为1;随后客户端进入SYN-SEND阶段。
- 第二次握手:服务器接收到来自客户端的TCP报文后,结束Listen阶段,并返回一段TCP报文,其中:标志位为SYN和ACK,表示确认客户端的报文seq序号有效,服务器能正常接收客户端发送的数据,并同意创建新连接;序号seq=Y;确认号Ack=X+1,表示收到客户端的序号seq并将其值加1作为自己确认号ACK的值;随后服务器进入SYN-RCVD阶段。
- 第三次握手:客户端收到来自服务器的确认收到数据的TCP报文之后,明确了从客户端到服务器的数据传输是正常的,结束SYN-SENT阶段,并返回最后一段TCP报文。其中:标志位为ACK,表示确认收到服务器发来的同意连接信号;序号seq=X+1,表示收到服务器端的确认号ACK,并将其值作为自己的序号;确认号为ACK=Y+1,表示收到服务器端的序号seq,并将其值加1作为自己的确认号ACK的值;随后客户端进入ESTABLISHED阶段。
在客户端与服务器传输的TCP报文中,双方的确认号ACK和 序号seq的值,都是在彼此ACK和seq值的基础上进行计算的,这样保证了TCP报文传输的连贯性。一旦出现某一方发出的TCP报文丢失,便无法继续握手,以此确保了三次握手的顺利完成。
为什么进行三次握手 为了防止服务器开启一些无用的连接增加服务器开销以及防止已失效的连接请求报文突然又传送到了服务器,因而产生错误。
四次挥手 FIN:释放一个连接
四次挥手就是TCP连接的释放。连接的释放必须是一方主动释放,一方被动释放。以下是以客户端主动发起释放连接的图解: 挥手之前主动释放连接的客户端结束ESTABLISHED阶段,随后开始“四次挥手”:
- 首先客户端想要释放连接,向服务器端发送一段TCP报文,并且停止在客户端到服务器端方向上发送数据,但是客户端仍能接收从服务器端传输过来的数据。这里不发送的是正常连接时传输的数据,而不是一切数据,所以客户端仍能发送ACK确认报文。
- 服务器收到客户端发出的TCP报文后,确认了客户端想要释放连接,返回一段TCP报文。随后服务器开始准备释放服务器到客户端方向上的连接。
前两次挥手既让服务器知道了客户端想要释放连接,也让客户端知道了服务器端已经接收到了连接释放的请求,于是,可以确认关闭客户端到服务器端方向上的连接了。
- 服务器端在发送确认报文后,停止在服务器端到客户端方向上的发送数据,但是服务器端仍能够接收到从客户端传输过来的数据。
- 客户端收到从服务器端发出的确认TCP报文,确认了服务器端已做好释放连接的准备,随后向服务器发送一段报文,并等待2MSL。
后两次挥手既让客户端知道了服务器端准备好释放连接,也让服务器知道了客户端已经收到自己准备好释放连接的确认报文段了。于是,可以确认关闭服务器端到客户端的连接,由此完成了四次挥手。
为什么握手是三次,挥手是四次 之所以是三次握手是因为在第二次握手时服务器端发送给客户端的TCP报文是请求连接和确认报文一起发送给客户端的。请求连接表示服务器端同意建立连接,确认报文表示告诉客户端,服务器收到了它的请求。 而四次挥手是因为释放连接报文和确认接收报文分别传输的。因为在收到客户端发来的释放连接请求时,服务器可能还有必要的数据需要处理,所以只能先发送确认报文,等准备好释放连接后再发送释放连接报文。
为什么客户端需要等待2MSL 为了确认服务器端是否收到客户端发出的ACK确认报文。
当客户端发出最后的ACK确认报文后,并不能确定服务器端是否收到,所以客户端会设置一个2MSL(MSL:一段报文在传输过程中的最大生命周期,2MSL即服务器端发出报文以及客户端发出确认报文的总时长)的计时器。在客户端发出最后一个确认报文段后,服务器端在1MSL内没有收到客户端发来的确认报文,就再次向客户端发送报文。如果客户端在2MSL内,再次收到了来自服务器端的FIN报文,说明服务器端由于各种原因没有接收到客户端发出的ACK确认报文。客户端再次向服务器端发出ACK确认报文,计时器重置,重新开始2MSL的计时;客户端在2MSL内没有再次收到来自服务器端的FIN报文,说明服务器端正常接收了ACK确认报文,客户端可以进入CLOSED阶段,完成“四次挥手”。
|