TCP三次握手和四次挥手

首先我们来回顾一下 TCP 的数据传输单元,TCP 传送的数据单元称为报文段。一个 TCP 报文段分为 TCP 首部和 TCP 数据两部分,整个 TCP 报文段都封装在 IP 数据报中的数据部分,TCP 首部长度是4的整数倍,其中有固定的20个字节,剩余的可变动的就是选项和填充「最常见的 可选字段是最长报文大小,又称为MSS(Maximum Segment Size),每个连接方通常都在通信的第一个报文段(为建立连接而设置SYN标 志为1的那个段)中指明这个选项,它表示本端所能接受的最大报文段的长度。」,20个固定的字节包括了源端口号(2 字节)、目的端(2 字节)、seq序列号(4字节)、确认号ack(4字节)、以及确认位ACK 等等。

1. 确认ACK,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;

2. 同步SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1, ACK=1;

3. 终止FIN,用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放;

其次,我们来详细讲解一下三次握手、四次挥手的过程:

三次握手:

首先,在三次握手建立连接的阶段,是不会传输 TCP 报文段的,传输的是 传输控制块(TCB), 传输控制块 TCB(Transmission Control Block)存储了每一个连接中的一些重要信息,如:TCP 连接表,指向发送和接收缓存的指针,指向重传队列的指针,当前的发送和接收序号等 等。

收到报文,发送报文,同时修改自身的状态,如果不发送报文,自身状态也不会改变

最开始的时候客户端和服务器都是处于CLOSED状态。主动打开连接的为客户端,被动打开连接的是服务器。

1.TCP服务器端创建传输控制块TCB模块,时刻准备接收客户端的连接请求,此时服务器就进入LISTEN(监听)状态。

2.TCP客户端也会先创建传输控制块TCB模块,然后向服务器发出连接报文,报文首部中同步SYN=1,同时选择一个初始序列号seq=x,此时客户端进程进入SYN-SEND(同步已发送状态)状态。SYN报文不能携带数据,,但是需要消耗一个序号。

3.TCP服务器收到客户端发送的请求报文,如果同意连接,就发出确认报文,SYN=1,确认序号ack=x+1,ACK=1,同时为自己初始化一个序号seq=y,同时TCP进入SYN-RCVD,这个报文也不能携带数据,但是也需要消耗一个序号。

4.TCP客户端收到服务端发送确认报文,还要向服务端发送确认。确认报文的ACK=1,ack=y+1,自己的序号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED状态(建立连接)。

5.TCP服务器收到客户端确认信息进入ESTABLISHED状态,此后双方就可以开始通信了。

1.为何不直接在第一次握手就带上报文段消息,非要第三次才可以带?

因为 TCP 是要保证数据的不丢失且可靠,如果在第一次就带上报文段消息,此次建立连接很有可能就会失败,那么就不能保证数据的不丢失了,在不可靠的机制上进行这种操 作,换来的代价太大,每次发送报文段的资源也会增大,得不偿失; 而第三次握手的时候,客户端已经知道服务器端准备好了,所以只要告诉服务器端自己准备好了就okay了,所以此时带上报文段信息没有任何问题。

2.可不可以只握手两次?

一句话,主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。 肯定是不可以的,三次握手主要是解决这样一个常见的问题,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没 有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求 连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。 如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就 知道客户端并没有请求连接。

四次挥手:

数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。

1. 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最 后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个 序号。

2.服务端进程收到客户端发送的断开连接的报文,发送确认报文确认序号ack=u+1,ACK=1,并带上序号为seq=v,此时服务端进入CLOSE-WAIT(关闭等待)状态。**TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数 据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,**也就是整个CLOSE-WAIT状态持续的时间。

3.客户端进程收到服务发来的确认报文,客户端进入FIN-WIAT-2(终止等待2)状态,等待服务器发送释放连接的报文(再次之前还需要接受服务器端发送的最后数据)。

4.服务器最后的数据发送完毕,就像客户端发送释放连接的报文,FIN=1,ack=u+1,由于服务器发送最后的数据假设序,假设此时序号seq=w,此时服务器进入LAST-ACK(最后确认)状态。等待客户端确认。

5.客户端收到服务器发来的释放连接的报文,发送确认报文ACK=1,ack=w+1,seq=u+1。客户端进入TIME-WAIT(时间等待)状态,经过2*MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后才进入CLOSED状态。

6.服务器收到客户端的确认报文,进入CLOSED状态。

为什么客户端在收到 服务器端发来的 FIN 包后要等 2 个最长报文段传输时间?

防止最后自己发去的 ack 没传送到服务器,如果服务器没收到客户端的 ack,肯定会选择重发一次 FIN 包,那么此时如果客户端已经关闭了,客户端就不能再发 ack 确认收到 了,至于为何是 2 个报文段传输时间,因为刚好一去一回嘛… 2 个最长报文传输时间没有 FIN 包发来,就说明服务器已经关闭了,客户端也就可以安心关闭了。

如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设 置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出 了故障,接着就关闭连接。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值