【JavaEE】——四次挥手,TCP状态转换,滑动窗口,流量控制

简介: 四次挥手、TCP状态转换、(listed,established,close_wait,time_wait),滑动窗口,ack丢包,数据丢包,流量控制

  image.gif 编辑

阿华代码,不是逆风,就是我疯

你们的点赞收藏是我前进最大的动力!!

希望本文内容能够帮助到你!!

目录

一:断开连接的本质

二:四次挥手

1:FIN

2:过程梳理

3:能合二为一吗?

三:“三次握手”和“四次挥手”异同

1:相同点

2:不同点

四:TCP连接状态转换

1:TCP状态转换图

2:LISTED

3:ESTABLISHED状态

4:CLOSE_WAIT(面试高频)

(1)过程梳理

(2)作用

5:TIME_WAIT(面试高频)

(1)过程梳理

(2)作用

五:滑动窗口

1:批量传输

2:滑动窗口

3:ack丢包

4:数据丢包

(1)快速重传

注意点①

注意点②

(2)优点

(3)总结

六:流量控制

1:缓存区上限

2:窗口动态变化


一:断开连接的本质

通过上一篇文章的学习,我们知道“三次握手”的目的和本质就是让通信双方能够保存对端的信息,当信息这个数据量过大的时候,就要引用数据结构。

那么断开连接的本质就是把对端的信息从数据结构中进行删除,释放掉

二:四次挥手

1:FIN

同样我们先认识一下TCP数据报包中,6个标志符中的FIN——结束报文段

单词为finish(结束)——>缩写为FIN

在之前的学习中,我们调用通过ServerSocket类调用close方法就会触发FIN,这里的FIN也是在内核中完成。

同样如果我们结束一个进程也会触发FIN【JavaEE】——TCP回显服务器(万字长文超详细)-CSDN博客

image.gif 编辑

image.gif 编辑

2:过程梳理

引入:与“三次握手”中“一定是客户端先主动”不同,“四次挥手”中服务器和客户端两者谁都可以先主动(分手像极了爱情~)这里我们用“客户端先主动”充当例子

(1)客户端发起FIN(结束报文段)

image.gif 编辑

(2)服务器ACK应答并且也发起FIN(结束报文段)

image.gif 编辑

(3)客户端ACK应答

image.gif 编辑

3:能合二为一吗?

引入:在上述图解步骤下,服务器和客户端各自给对方发起FIN,并再给对方返回ACK,“四次挥手”后代表着通信双方“和平分手”。那么这里的②③步骤是否也能“合并”呢?

答案是:可以合并,但是不能100%的合并——“如合~”

如果②③两者发送的时间间隔很长,那么就不能合并

三:“三次握手”和“四次挥手”异同

1:相同点

都是需要有一端先发起SYN/FIN,然后对端在返回ACK

传输顺序:syn/ack/syn/ack     fin/ack/fin/ack

2:不同点

三次握手中中间两次一定能够合并,四次挥手中中间来那个词不一定能够合并

三次握手中一定是客户端先主动,四次挥手中谁先主动都可以

四:TCP连接状态转换

引入:在TCP的连接中,数据结构会保存两端的信息,在这里面就有一个属性,叫做“状态”,操作系统可以根据状态的不同,决定应该对连接做什么

1:TCP状态转换图

image.gif 编辑

铁铁们看到这个图脑壳都大了吧,俺也是,这里我们只介绍几个比较重要的状态即可

2:LISTED

listed(译为:已登录的)表示:服务器这边已经建立好了ServerSocket,并且绑定好了端口号,随时准备接收客户端的连接

image.gif 编辑

步骤一:我们先启动服务器(代码在之前TCP回显服务器那一篇文章,直接复制粘贴即可)

【JavaEE】——TCP回显服务器(万字长文超详细)-CSDN博客

image.gif 编辑

步骤二:打开命令窗口,输入netstat -ano

image.gif 编辑

步骤三:服务器加上限制条件,我们看9090这个在代码里选择连接的端口

image.gif 编辑

3:ESTABLISHED状态

注:established(译为:已建立的)

表示:客户端和服务器已经建立完毕(三次握手完了)

步骤四:客户端和服务器连接进入ESTABLISHED

注:这里双方进入时间差极小,肉眼是看不出来先后顺序的,除非精确查看日志里的时间戳

image.gif 编辑

4:CLOSE_WAIT(面试高频)

close_wait(译为:关闭等待)——谁被断开连接,谁进入close_wait状态

(1)过程梳理

看图客户端发起FIN断开连接(四次挥手),服务器收到后发送ACK应答报文后进入close_wait状态。

这个状态是比较难观察到的,因为服务器发送ACK和FIN的时间间隔极短,即关闭socket文件的时间极短,此时close_wait -> last_ack 状态的切换非常快

(2)作用

阻塞等待客户端数据请求

注:如果发现服务器或者客户端出现大量的CLOSE_WAIT,意味着很可能是socket没有关闭,出bug了。

image.gif 编辑

5:TIME_WAIT(面试高频)

谁主动断开连接,谁进入TIME_WAIT状态

(1)过程梳理

服务器返回给客户端ASK和FIN,客户端收到返回ASK应答后,进入TIME_WAIT状态

(2)作用

如果最后一个ACK丢包了,服务器迟迟收不到ACK,就会重传一个FIN,客户端收到后也会相应重传一个ACK。

TIME_WAIT就为这个过程留下充足的时间,这个等待的时间不是无休止的等待(连机器都不会无限制的等待,更何况爱情呢~),最多2MSL(MSL是系统内核的配置项)

五:滑动窗口

引入:之前我们简单了解一次数据传输,所经历的过程。

我们可以发现一个问题:发一个数据就要等一个ack,这样的效率是不足以满足现在“信息爆炸”的现状的。

所以我们引出:批量传输这个概念

1:批量传输

顾名思义——先发一个数据,不等ack了,下一个数据接着发,连续发了好多个ack之后,使用同一份时间来等待ack

好处:减少了总的等待的时间内(下面这张图能非常形象的表现出来)

image.gif 编辑

2:滑动窗口

image.gif 编辑

3:ack丢包

看图——

image.gif 编辑

1001的ack应答丢包了,但是2001这个ack没有丢包,主机A收到②这个ack后就知道主机B2001之前的数据都收到了,所以①号ack丢包问题不大,这种情况无需处理,对于TCP传输的可靠性没有影响。

4:数据丢包

image.gif 编辑

(1)快速重传

注意点①

看上图,主机A发送的1001~2000这个数据丢包了,但是2001后面的数据还在发送,此时主机B就会对2001后面的数据,返回ack,多次强调下一个数据是1001,服务器收到三次这个ack之后,就知道1001~2000这个数据丢包了,就会重传(有点超时重传的感脚~)

注意点②

主机B收到1001~2000这个丢包的数据后,直接会跳到索要7001这个数据包了,而不是2001~。

这是因为TCP有一个接受缓冲区,你可以想象成一个队列 image.gif 编辑

(2)优点

上述重传的过程,整体效率非常高,做到了“针对性”的丢包重传,不必重新发送,这种重传叫做“快速重传”

(3)总结

①“确认应答”、“超时重传”、“滑动窗口”、“快速重传”这四种机制并不冲突,可以同时存在。

②短时间发送了很多数据,窗口才滑的起来

③判定丢包的标准是:连续有多个ack索要同一个数据;普通传输判定标准是:ack超时没有到达

六:流量控制

引入:上述滑动窗口可以提高数据的传输效率,窗口越大,更多数据复用同一块时间,效率就更高,那么问题来了,窗口越大越好吗?显然不行

1:缓存区上限

数据到达接收方是先暂时存储在缓冲区当中,等到一定的数量后,接受方在一次性拿(read)出来

试想发送方如果一下子发送数据太快,导致接收方的缓冲区装不下了,就会导致丢包,这时在重传也没用了(因为已经返回ack了)

2:窗口动态变化

与其等待接收方缓存区满了,不如提前感知到,就减慢发送数据的速度,(下面有请我们的老朋友)

image.gif 编辑

image.gif 编辑

16位窗口大小,就能很好的动态控制窗口的大小,通过这个字段,来给发送方反馈发送速度,很明显这个字段对于发送方的报文中没有意义,只有ack报文中才有意义

注:这个16位并不是实际上的大小——在TCP报头中有一个参数叫做窗口扩展因子

      实际窗口大小 = 16位窗口大小* 2^窗口扩展因子

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
12月前
|
缓存 安全 Java
【JavaEE】——单例模式引起的多线程安全问题:“饿汉/懒汉”模式,及解决思路和方法(面试高频)
单例模式下,“饿汉模式”,“懒汉模式”,单例模式下引起的线程安全问题,解锁思路和解决方法
|
12月前
|
SQL Java 数据库连接
MyBatis-Plus高级用法:最优化持久层开发
MyBatis-Plus 通过简化常见的持久层开发任务,提高了开发效率和代码的可维护性。通过合理使用条件构造器、分页插件、逻辑删除和代码生成器等高级功能,可以进一步优化持久层开发,提升系统性能和稳定性。掌握这些高级用法和最佳实践,有助于开发者构建高效、稳定和可扩展的企业级应用。
714 13
|
12月前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
581 73
|
12月前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
505 12
|
12月前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
364 12
|
12月前
|
存储 前端开发 Java
【SpringMVC】——Cookie和Session机制
获取URL中参数@PathVarible,上传文件@RequestPart,HttpServerlet(getCookies()方法,getAttribute方法,setAttribute方法,)HttpSession(getAttribute方法),@SessionAttribute
648 11
|
12月前
|
JavaScript 前端开发 API
【JQuery】基础从零入门操作,简单详细
jQuery下载,引入依赖,JQuery语法、选择器、时间、获取元素、返回CSS、修改属性、添加元素、删除元素、猜数字游戏、表白墙
514 11
|
12月前
|
JSON 前端开发 Java
【Bug合集】——Java大小写引起传参失败,获取值为null的解决方案
类中成员变量命名问题引起传送json字符串,但是变量为null的情况做出解释,@Data注解(Spring自动生成的get和set方法)和@JsonProperty
|
12月前
|
存储 JSON 前端开发
【Spring项目】表白墙,留言板项目的实现
本文主要介绍了表白墙项目的实现,包含前端和后端代码,以及测试
|
12月前
|
算法 索引
【算法】——二分查找合集
二分查找基础模版和进阶模版,查找元素位置,搜索插入位置,x的平方根,山脉数组的峰顶索引,寻找峰值,点名