首先,TCP能够是一种可靠的传输原因就是TCP的三次握手和四次断开的存在。本篇文章就带大家详细的了解和认识一下TCP的三次握手和四次断开。
SYN:同步序列号。它表示建立连接。tcp规定SYN=1时不能携带数据,但是要消耗一个序列号,因此随机选取一个序列号为seq=x,此数据包是一个标记seq,不携带任何数据。
ACK:确认序号,用来表示相应(ACK=1表示确认连接成功) 因此,SYN和ACK都为1时代表连接之后的响应,而只是SYN=1,表示的只是连接。
seq:(sequence number)序列号,它是发送端数据包的初始序列号,seq=x表示发送端数据包的初始序列号为x(seq=0代表第0帧)
ack:(acknowledge number)确认号,它是对这次收到数据包的确认,以及对下次收到数据包的期待。ack=x+1表示我方到x为止的所有数据都已经正常收到,且告知对方期望下次收到的包初始序列号是x+1
其中SYN/ACK是协议层面的标记,而seq/ack是属于数据层面的标记。
三次握手的过程:
首先,客户端向服务端发送请求连接,SYN=1,seq=x,ACK=0,因为要建立连接,所以SYN=1,SYN=1时不能携带数据但是要消耗一个序列号,所以seq=x(x是随机数)因为没有响应动作,所以ACK=0 发送之后客户端进入syn_sent状态,表示客户端等待服务器端的回复
其次,server收到请求后,再向client发送确认,SYN=1,ACK=1,seq=y,ack=x+1;因为要建立连接,所以SYN=1,所以seq=y,ack=x+1代表服务端到x为止的所有数据都已经正常收到了,而且告诉客户端希望下次收到的序列号是x+1 发送后服务端进入syn_rcvd状态,表示服务器端已经收到了客户端的连接请求,等待客户端的确认
最后,客户端收到确认后还需要再发送确认,同时携带要发送给server的数据ACK=1,seq=x+1,ack=y+1;连接建立
因为有响应动作,所以ACK=1,当前发送的数据包x都被对方接收,自己也接收到了对方到y的数据包,所以自己的seq=y+1表示下次想要接收的数据包序列号是y+1.
server收到后,这个TCP连接就进入了Established(已确认)状态,就可以发起http请求了。
四次断开:
step1:
客户端发送一个FIN,用来关闭客户端到服务器端的流量传送,等待服务器确认。
step2:
服务器收到这个FIN,它发送一个ACK,确认ACK为收到的序列号加1。
step3:
关闭服务器到客户端的连接,发送一个FIN给客户端,请求客户端关闭流量传送。
step4:
客户端收到FIN后,发回一个ACK报文确认,并将确认序列号seq设置为收到序列号加1.首先进行关闭的一方执行手动关闭,而另一方执行被动关闭。
到达这一步骤后客户端进入TIME_WAIT状态。等待2msl后自动关闭。
Q&A:
Q:为什么三次握手只需要三次而四次断开却需要四次?
A:三次握手的第二次收到和请求可以同时发送,是因为在还没有建立起来对话的时候双方没有流量传输,所以不会有其他的影响,但是,但是,但是(划重点),四次断开时基于连接的状态发起请求的,在收到对方的FIN报文通知时仅仅表示对方没有数据发送给你了,但未必你的所有数据都发送给对方了,所以你不会立即关闭socket,也即你可能还需要发送一些数据给对方后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。