网络协议:TCP Part2

本文深入探讨TCP连接的四次挥手过程,包括经典挥手的状态转移、挥手变形及特殊情况。详细阐述了CLOSE_WAIT和TIME_WAIT状态的特点,以及这两种状态在面试中的常见问题。此外,还分析了TCP的流量控制和拥塞控制机制,以及TCP协议在异常情况下的处理策略。最后,总结了TCP连接的整体过程和关键机制。
摘要由CSDN通过智能技术生成

目录

四次挥手

经典四次挥手

经典挥手的状态转移

挥手变形

三次挥手

 同时关闭

 CLOSE_WAIT 状态

特点

 常考面试题

TIME_WAIT状态

特点

面试题1

为什么TIME_WAIT时间是2MSL?

 面试题2

TCP协议和应用层不同的观察现象

挥手阶段总结

TCP中的异常

大情况1:OS正常参与操作来关闭连接

1.任务管理器结束

2.关机结束

3.重启结束

大情况2:OS代码执行不了—长按关机键/断开电源

首先,要分析甲主机的命运

再来分析乙如何处理

收到异常的标志位 —— RST

流量控制

流量控制

接收窗口

1.如何实时地知道对方的接收能力呢?

2.当拿到对方的接受能力,准备发送流量

3.滑动窗口机制

拥塞控制

拥塞窗口

 整体步骤

面向字节流特性

总结部分

TCP segment Header部分总结讲解

TCP Connection整体过程总结

 滑动窗口何时变化

连接阶段的一些机制 

忽略ack丢失

立即重传

更新接收窗口 

 延迟应答/捎带应答

 TCP协议手动设置边界

 TCP协议总结

 TCP与UDP对比

 拓展问题


四次挥手

标志位: (FIN)   Final/Finsh

挥手也分为主动挥手和被动挥手,但不意味着主动挥手方就是主动连接方

若两方连接同时关闭,那么两端都是主动连接方

经典四次挥手

经典的四次挥手和握手差不多,只不过并没有合并syn和ack

但是握手的时候时必须合并的

经典挥手的状态转移

 双方的起点都是established状态

然后,经过主动挥手方的FIN,然后被动挥手方回应ack。当一段时间过去后,被动挥手方发送FIN和ack。

挥手变形

三次挥手

挥手的segment也是可以合并的,只不过因为握手必须合并,所以握手只能是三次

 落实到状态转移图上就是:

这张图有点问题,在我看来close_wait状态之后再进行ACK和FIN的发送

 同时关闭

两端自己发送FIN 和 ACK 

  落实到状态转移图上就是:

 CLOSE_WAIT 状态

特点

1.此状态发生在被动方

2.在单方面分手时,会出现这种情况

 常考面试题

当服务器出现大量CLOSE_WAIT状态的TCP连接,这种现象是否合理?

答:合理与否要看具体情况:

1.如果是因为程序设计时,会出现比较长时间的单方面关闭情况,就是合理的。

2.如果不是的话就不合理,大概率是出现CLOSE_WAIT这一端的socket.close()忘记关闭了。

再者说,大量这个词,是要根据比例决定的,不是数量

TIME_WAIT状态

特点

1.发生在主动方

2.在挥手基本结束的情况下出现

面试题1

问:既然回收的工作完成了,不是直接进入CLOSED状态,而是进入TIMED_WAIT状态呢?

答:当进入这个状态,而不是直接进入CLOSED状态,主要原因是因为我们还要发送一个ack文件,我们不知道能不能发送成功,所以不能立刻放开连接,得再等一段时间。

情况一:

对方没有收到ack的话,就会重发FIN,这个时候要是释放连接了就不知道咋办了。

 情况二:

我们知道连接是通过五元组信息确定通路的,那么如果我不经过TIMED_WAIT 把五元组直接分配出去的话,这个五元组在收到信息算谁的就不好说了。

为什么TIME_WAIT时间是2MSL?

 MSL: Maximum Segment Live:一个Segment能在网络上活着的最大时间。2*MSL时间过去之后,segment的一个来回肯定是够了。

说明:

1.对方"一定“最后一个ack (即使对方没有收到,再发送的fin我们也没有收到,说明网络出问题)

2.网络上肯定没有发送给甲的segment 了,所以收到的segment一定是给乙的

ps:
MSL是个理论值,实际中很多OS 取的是经验值,一般取1分钟。所以默认情况下,

TIME_WAIT持续的时间是2分钟。但这个值可以修改。

 面试题2

当服务器出现大量TIMED_WAIT状态的TCP连接,这种现象是否合理?

答:

理论上说,合理,我们只是正常进行关闭程序

但事实上这样不太好

维护连接是需要成本的(最主要的比如硬件中的内存) ,就算是我可以背负这个成本,最好也是由客户端来背负而非服务器,因为服务器需要连接的太多了,客户端相对会轻松很多。

所以,一般做网络编程设计时,也不推荐服务器主动关闭连接(排除某些情况)

TCP协议和应用层不同的观察现象

TCP能看到的就是三次握手过程 ——>建立连接 ——> 四次挥手

应用层能看到的基本上是一个代码的过程

 另外要说的一点是,主被动连接方,发送接收者,主被动关闭方之间没有关系,不可以混为一谈。

挥手阶段总结

1.四次挥手,为啥不说三次。

2.四次挥手的三种情况

3.四次挥手的tcp header的标志位变化

4.四次挥手的状态变化

5.其中CLOSE_WAIT和TIME_WAIT做重点学习。

TCP中的异常

连接起来的两个进程究竟在何时抛出异常,何时正常处理捏,我们分为这几种情况。

大情况1:OS正常参与操作来关闭连接

1.任务管理器结束

2.关机结束

3.重启结束

都是正常关闭socket.close

大情况2:OS代码执行不了—长按关机键/断开电源

我们需要分开讨论连接最后的处理情况:

例如甲乙主机相连,我们断开甲的连接

首先,要分析甲主机的命运

甲主机没有进行任何OS操作,直接消失在连接中,不是正常关闭,也不是异常关闭,是直接消失

再来分析乙如何处理

在乙的世界中,目前的连接并未断开,我也不知道甲已经消失了。因此,我们需要看情况讨论接下来的处理:

1.如果乙中存在写事件

这样的话就比较容易办了,那边收不到消息就发不回来ack,过一段时间就会发生超时重传,如果重传尝试多次未果,我们会走异常处理:

1.关闭该TCP连接

2.以异常的方式通知应用层(Java)

3.再发最后一条 reset segment 来通知对方,该连接异常关闭了,对方收得到收得到与我无关了

2.如果只存在读事件

如果只是读数据的话,本来也就不会收到ack,这样的话我们咋办呢?

1.TCP的keeyalive机制 : 就算我们只读数据,我们也会定期发送一些数据给对方(数据内容可以为空),目的就是看看对方有没有ack发送回来(使用不多)

2.应用层自己做工作:

1).我们 read 的时候,加上一个超时时间 —— read timeout

2).定期双方给对方发消息 —— heartbeat(心跳包)

收到异常的标志位 —— RST

Reset segment 

当我们收到这个标志位打开的segment时就说明异常了,我们需要立刻关闭连接(不需要挥手),并且以异常的方式通知应用层

流量控制

我们讲的广义上的流量控制,是通过对方的接收能力和网络承载能力来动态的调节自己的发送流量,以此来提高到达率。

狭义上的流量控制那么就是根据对方的接收能力来判断自己的发送流量,拥塞控制则是通过网络承载能力来判断自己的发送流量。下面我们分别来说一说。

流量控制

通过对方的接受能力来控制自己的发送量。

流量控制分为以下几步:

知道对象的接收能力——拿到对方的接收能力——通过发送方滑动窗口机制来控制发送量

接收窗口

首先我们理解一下接收窗口的概念: 

接收窗口是接收缓冲区的未使用大小

1.如何实时地知道对方的接收能力呢?

当然是要对方来告诉我们,对方可以通过以下方式告诉我们信息:

1.在所有要发送的segment中携带接收能力(接收窗口)

2.即使有一段时间不发送数据,也要发送ack+window给对方

2.当拿到对方的接受能力,准备发送流量

我们的最大发送量其实就是对方的接收窗口大小。

3.滑动窗口机制

滑动窗口存在于发送缓冲区,我们应用层会把所有需要发送的数据放入缓冲区,然后我们滑动窗口就是在这个数据中的一个窗口,但大小由接收缓冲区的window决定,会实时变化。

第一步:三次握手,可以在自己的发送区来划分得到对象的接收窗口大小。

 第二步:由应用层写入需要发送的所有数据

这里可能滑动窗口很大,我们可以把数据全部放在滑动窗口里,不然会溢出,存在于滑动窗口外。

 第三步:发送一部分数据到接收端

 第四步:根据返回来的ack和新的接收窗口,改变滑动窗口

ack已应答的数据就说明对方的应用层已经接收了,这是唯一可以使我们的滑动窗口左侧向前移动的方式。

至于滑动窗口的右侧向前移动的方式,由接收端发送回来segment中的接收窗口来决定,我们的滑动窗口就是这个大小。

拥塞控制

拥塞控制就是广义上流量控制的另外一种判断方式,他通过网络的承载能力来对发送量进行控制,不同于接收窗口那种直接能得到信息的形式,拥塞窗口是需要计算的。

拥塞窗口

拥塞窗口不是一个精确值,而是一个通过动态算法计算出来的估算值。

我们将丢包率作为重要因素来推算拥塞窗口

丢包率 = 单位时间内,TCP重发的次数占比。

 整体步骤

1.得到接收窗口和拥塞窗口大小。

2.发送最大流量的大小就是 min(接收窗口,拥塞窗口)

3.根据以上结果构造滑动窗口

面向字节流特性

正因为由流量控制,拥塞窗口的特性,我们无法一次性把数据全部发送过去,所以TCP是面向字节流的。

总结部分

TCP segment Header部分总结讲解

Header部分基本都说了,下图中对两个还没讲的标志位进行了说明,并对之前说的内容进行了总结。

 

TCP Connection整体过程总结

这里的东西之前都讲过,我就直接盗图了

落实在状态转移上,我们能记住三次握手就可以,能多记就多记

 

 滑动窗口何时变化

这个上面也讲了,

左侧只随着ack里面已接收数据的大小而改变

右侧要看流量控制后,接收窗口和拥塞窗口的大小,还要看ack,也就是左侧如何变化的,右侧可以同时右移。

连接阶段的一些机制 

忽略ack丢失

这是种特殊情况,当我们中间的ack没收到,但是后面的ack收到了,就不需要管前面了。

立即重传

默认情况是:超时重传

我们现在说的情况是: 当连续收到相同ASN时,直接重传

更新接收窗口 

即使一段时间内没数据,也要发送自己的接收窗口大小给对方。

 延迟应答/捎带应答

可以来延缓应答时间,这个叫延迟应答,如果下一次数据也来了,那么我一起应答回去就好了,

我们在发送数据回去时,也可以发送应答回去,这个叫捎带应答,两个可以配合使用。

 TCP协议手动设置边界

 应用层的协议设计是我们必须手动设置边界

方法:

1.发送定长消息

2.先发长度,再发数据

3.用特殊字符分隔

 TCP协议总结

 因为都是之前讲过的,直接上图了。

 TCP与UDP对比

也上图了

 拓展问题

这种问题,我们就按照模仿TCP协议来回答即可。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值