【Javaee】网络原理—TCP协议的核心机制

news2024/11/25 2:31:33

前言

TCP/IP五层协议是互联网中的主流模型,为网络通信提供了一个稳固的框架。

主要包含了应用层,传输层,网络层,数据链路层,物理层。

本篇主要介绍传输层的TCP协议的核心机制


一.  确认应答(ack)

TCP最核心的机制为可靠传输,但可靠传输并不是保证100%的成功,而是尽可能的使数据能到达对方,可靠性的保证有两个重要机制

1.能感知到对方是否接收到数据

2.如果发现对方没有收到,就要进行重发

其中,通过确认应答机制来感知对方是否收到。

所谓的“感知对方是否收到”,是靠对方的通知。

应答报文(acknowledge),缩写为ack

网络传输中存在着后发先至的情况,当发送多个消息时,上诉机制可能可能产生问题,例如

甲向乙提出两问题,乙回答时可能发送后发先至的情况,变成了乙不同意一起吃饭,却同意做女朋友,此时,就产生了歧义。

此时,可以给传输的数据添加编号,通过编号,可以区分出数据的先后顺序。

 TCP是面向字节流的,实际上的编号是按照字节来编号的。

按照字节编号这样的机制,就是TCP的序号

在应答报文中,针对之前收到的数据进行对应编号,称为TCP的确认序号

其中,确认序号是接收方收到的数据最后一个字节序号的下一个序号(如上图,数据最后一个字节序号是1000,ack则返回1000+1,也就是1001作为确认序号)

确认序号前的数据,全部都已经被接收方接收

如果数据在发送过程中发生后发先至,后面的数据比前面的数据先一步到达,此时接收方read就会进入阻塞等待,直到读取到开头发送的数据,确报发送方write的顺序和接收方read的顺序相同时,才会解除阻塞。


二.超时重传

网络传输中并不是一帆风顺,常常会发生丢包情况

产生丢包的原因有多种

1.数据传输过程中,发生了bit翻转,收到这个数据的接收方计算校验和对不上,此时会直接丢弃该数据包。

2.数据传输到某一节点,节点负载太高了(网络高峰期),后续传输过来的数据可能直接被节点丢弃掉

TCP需要通过应答报文来区分数据是否丢包,收到应答报文(ack),就说明数据没有丢包,没收到应答报文,就说明数据丢包了。

丢包是难以预测的,TCP再强大也难以完全避免丢包,能做的只有在感应到数据丢包时重新发一次

但数据在网络传输是需要消耗时间的,“没收到应答报文”可能只是暂时没收到,等一会可能就收到了,也有可能是确实丢失,永远收不到了。

超时重传机制通过设定一个“时间限制”,如果在这个时间限制内,没有收到ack,则视为数据丢包,随后重传文件

如果数据成功发送,但ack丢包,由于发送方无法识别对方有没有收到数据,到达限制时间后也会进行重新发送,此时接收方又收到了一份相同的数据,TCP会进行去重,确保不会read到同样的数据。

超时重传的时间不是固定不变的,而是动态变化的。

发送方第一次重传,超时时间是t1,如果仍然没有ack,则会进行第二次重传,超时时间为t2

通常情况下t2>t1,每重传一次,超时时间的间隔就会变大,反复重传多次后,都没有顺利到达,TCP不会尝试重传,会先进行复位连接,发送一个一个特殊的数据包(复位报文),如果网络这会恢复了,复位报文会重置连接,使通信可以继续运行,如果网络存在严重问题,复位报文也没得到回应,此时TCP就会单方面放弃连接,连接也就无了。

确认应答和超时重传相互补充,共同构建了TCP的可靠传输机制


三.连接管理★★★(重点)

1.建立连接(三次握手)

三次握手是客户端与服务器建立连接的过程,前面提到过,连接的实质是双方保存着对方的信息

如上图所示,A请求保存B的信息,B接收到后返回ACK,然好B请求保存A的信息,A收到后返回ACK,其中,syn和ack可以同时发送,于是将这两步合并成一步,这就是三次握手。


三次握手要解决说什么问题?意义所在?

1.投石问路,初步验证通信链路是否畅通(可靠传输的前提条件)

2.确认通信双方各自的发送能力与接收能力是否都正常

3.让通信双方在通信前,对通信过程中需要用到的一些关键参数进行协商(TCP通信时的起始数据序号,就是通过三次握手协商确定的)

上诉约定的意义,在于避免“前朝的剑斩今朝的官”

假如A和B在传输数据时,数据包传输的慢,突然A和B断开了连接,过了一会A和B又重新建立了连接,虽然还是A和B两个主机连接,但可能是不同的应用程序,此时上一个没到达的数据包可能这时才到达,A和B已经是新的连接了。

针对这样“迟到”的数据包,应当直接丢弃掉。

那么,如何区分数据包是否是前朝的?

可以给每个连接都协商不同的起始序号,如果发现收到的数据和起始序号以及和最近收到的序号差距很大,则为“迟到”的数据包


2.断开连接(四次挥手)

断开连接就是通信双方各种把对端的信息删除掉(优雅的)

前面介绍“超时重传”时提到单方面释放连接,则是没那么优雅的进行断开连接(会造成资源浪费)

通信双方各种给对方发送“FIN”,各自给对方返回“ACK”

三次握手的三次,是因为中间的syn与ack进行了合并

对于四次挥手来说,中间ACK和FIN不一定能够合并。

原因是四次挥手ACK是内核控制的,但FIN的触发则是通过应用程序调用close

这中间存在着时间间隔

3.TCP的状态

1)LISTEN状态

服务器进入的状态,表示已经绑定好端口,服务器初始化完毕,准备连接客户端

2)ESTABLISHED

客户端和服务器都保存好了对方的信息,可以传输后续数据业务(三次握手后)

3)CLOSE_WAIT

被动断开连接的一方进入的状态,等待代码执行close方法

如果发现服务器端存在大量CLOSE_WAIT状态的TCP连接,说明服务器代码可能存在问题,应检查代码是否有close操作

4)TIME_WAIT

主动断开连接的一方进入的状态,此处的TIME_WAIT按照时间等待,达到一定时间后连接也就释放了。

为何不直接释放连接?而是要等待一段时间??

TCP在传输的过程中,任何一个数据都有可能丢包

此处的等待,就是以防最后一个ACK丢包,如果最后一个ACK丢包,则会重传FIN

 能够重发一次ACK的前提是A这边的连接不能释放(如果释放就无法返回数据)

保留一段时间没有收到重传的FIN,则说明刚才的ACK应该是收到了,就可以释放连接

TIME_WAIT持续时间通常为2MSL

四.滑动窗口

1.概述

提起滑动窗口,学过算法的同学应该知道,算法思想中也有滑动窗口,其实,算法中的“滑动窗口”正是借鉴自TCP的滑动窗口

为什么TCP要滑动窗口???
TCP希望能在可靠传输的基础上,也能有不错的效率,为此引入滑动窗口。

此处的提高效率,只是“亡羊补牢”,使传输的效率损失尽可能降低(效率低于UDP)

按照以上方式(无滑动窗口),A每次发送一个数据给B,都得等待B的ack才能发下一个,这种方式的低效的。

改进方案则是把“发一个等一个”改成“发送一批等待一批”,把多次等待ack的时间合并成一次,这样等待的时间少了,效率也就提高了。

批量发送的数据越多,效率越高,此时把批量发送数据且不需要等待的数据的量称为窗口大小

以下图为例,主机A批量发送数据包后,当收到第一个ack后,就会立即发送下一条数据,窗口向右移动

2.丢包问题

情况一

数据包抵达,ACK丢包(如图)

此时不需要做任何处理,批量发数据,ACK丢失也只是丢失其中的一部分,不可能全丢了

通过确认序号,可以判定前面的数据都收到了,接下来要发送的数据就从确认序号这里往后发

情况二

发送方数据丢包

如图,确认序号会在收到后面的数据包时反复返回丢失段数据包的序号,提醒发送方进行重发,发送方识别出哪个数据包丢失后,针对这个数据包进行重传,其他顺利到达的数据包无需重传,这就是“快速重传”

快速重传可以视为滑动窗口下搭配的超时重传。


五.流量控制

滑动窗口窗口的大小对于传输数据的性能是直接相关的

窗口的大小不能无限的大,通信是双方的事情,发送方发送的快了,也得确保接收方能够处理的来。

发送方与接收方之间,有着一个接收缓冲区,用于存放发送方发送的数据(本质为阻塞队列)

如果发送速度特别快,接收方处理接收速度比较慢,就会使接收缓冲区充满,此时发送方强行发送数据则会丢包,这就需要让接收方的处理能力反向制约发送方的发送速度。

可以通过“定量”的方式,来实现制约

如果空闲空间越大,则可以认为应用程序处理速度比较快,就可以让发送方发送的快一些,设置一个更大的窗口大小。

如果空闲空间小,则可以认为应用程序处理速度比较慢,就可以让发送方发送的慢一些,设置一个更小的窗口大小shu

TCP接收方接收到数据的时候,就会把接收缓冲区剩余空间大小通过ACK数据包反馈给对方,例如

 流量控制,并不是TCP独有的机制,其他的协议可能也会涉及流量控制


六.拥塞控制

拥塞控制与流量控制是有关联的,也是“踩刹车”

虽然TCP有了滑动窗⼝这个⼤杀器,能够⾼效可靠的发送⼤量的数据.但是如果在刚开始阶段就发送⼤量的数据,仍然可能引发问题。

因为⽹络上有很多的计算机,可能当前的⽹络状态就已经⽐较拥堵.在不清楚当前⽹络状态下,贸然发送⼤量的数据,是很有可能引起雪上加霜的。

如下图,有一个节点本身负载已经很高,如果A依旧快速发送数据包,这个节点可能就直接丢包了

但由于中间节点数量多,每次传输数据走的路径还不一样,哪一个节点负载高难以精确的发现

那么要怎么衡量节点的负载来控制发送速度?

拥塞控制中,把中间传输的节点,视为一个整体,不关注具体的实现细节。

通过做实验的方式,找到一个合适的发送速度(面多加水,水多加面)

例如:1.先按照一个比较小的速度发送数据,数据非常畅通,没有丢包,说明网络传输数据整体比较畅通,就可以加快发送速度

2.增大到一定的速度后,发现丢包了,说明网络上可能存在拥塞,就减慢发送速度

3.减速到一定速度后,发现不丢包了,则又开始增加数据发送速度

........

如此反复

拥塞控制的窗口是动态变化的,需根据实际情况来调整

拥塞控制和流量控制都是踩刹车,这两个机制会同时起作用,最终实际发送发送窗口的大小,取决于上述两个机制得到的方式窗口的较小值。

流量控制与拥塞控制都是对TCP可靠传输的补充
 


七.延时应答

延时应答的目的是为了提高效率,尽可能降低可靠传输带来的性能影响。

发送方发送数据时,接收接收后不着急马上返回ack,而是数据发送一定数量(或可以按照一定时间)后,再返回ack。


八.捎带应答

捎带应答是再延时应答的基础上,提高效率的机制

把返回的业务数据和ack合二为一(减少包的数量,提高效率)。

正常情况下,发送方和接收方数据发送为“一问一答”,ack和发送数据业务之间存在着时间间隔,无法合并。

但是ack有着延时应答,可以将ack发送的时间往后拖,这一拖,可能赶上发送数据业务的时间,于是发送数据业务时,可以把ack也一起带上。

四次挥手中,FIN和ACK无法合并也是因为两个数据包之间存在着时间间隔。

但如果此时触发延时应答,ACK等待FIN发送时捎带发送,那么四次挥手也能够变成三次挥手


九.面向字节流

TCP协议传输时是通过字节流传输的,前文已经介绍过,这里主要介绍面向字节流所产生的粘包问题。

什么是粘包问题??

以图为例,当A向主机发送数据时,数据到达接收缓冲区

当应用程序读取接收缓冲区时,有各种读法(如aa,abb,bccc等),但“aaa”,“bbb”,“ccc”才是正确的读法,如不为这样的读法,应用程序读取的数据包与原数据包有所偏差,会产生不同的结果。

粘包问题就是应用层数据包在TCP缓冲区中连城一片,粘在一起。

应如何解决粘包问题?

方案一:

关键在于明确每个数据包的边界,可通过分隔符来区分包和包的边界。 

方案二:
约定每个应用层数据包的长度,利用数据包开头的两个/四个字节来定义长度


十.异常处理

在遇到一些异常情况时,TCP协议有着解决问题的方案

1)进程崩溃

在Java中表现为抛出异常,但没人catch,最终异常到了JVM里,进程直接崩溃

在这过程中,操作系统会进行善后,会关闭文件描述表里对应的文件,socket文件也会触发正常的关闭流程(四次挥手)

2)主机关机(正常流程)

操作系统会关闭掉所有的进程,关闭的过程中同样会进行四次挥手。

此时有两种情况

a)当四次挥手快时,四次挥手结束后主机关机

b)当四次挥手慢时,可能每来得及挥完就关机了(如图)

此时,B应没收到ACK,就会触发超时重传,可能会重传很多次,但达到上限后只能单方面主动放弃连接

3)主机掉电(拔电源)

分为两种情况

a)发送方掉电

此时B会发送探测报文,若A有ACK,说明A没有掉。

如果多次发送探测报文,没有回复,则认为A掉了

探测报文是周期性发送的,同时这个报文也是探测对方“生死”的,也被称为“心跳包”

b)接收方掉电

此时,B就不会发送ACK给A了,A会触发超时重传,重传的数据也没有响应,多次后会重置连接,重置连接没有响应后,A会单方面断开连接

4)网线断开

和主机掉电非常相似

站在A的视角,ACK收不到,超时重传,重置连接,最后单方面放弃连接

站在B的视角,探测报文没有回复,最后单方面放弃连接


TCP不只有10个机制,本篇只是提到较为核心的机制

以上便是全部内容,如有不对,欢迎指正

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2223670.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ESP32-S3学习笔记:常用的ESP-IDF命令总结

参考资料:1.esptool.py工具 2.idf.py工具 后续文章的讲解需要用到IDF命令行工具,当前文章简单介绍一下。 目录 打开命令行的小技巧 一、读flash信息 二、擦除flash 三、读flash数据 四、写flash数据 打开命令行的小技巧 大家安装完IDF开发包后…

关于小程序审核需要提交订单列表页面path的修改办法

小程序又又又又又搞事情啦~~~ 从12月31号起,所有有订单生成逻辑的小程序在审核过程中,必须要填写订单列表页面的path才可以进行审核 在代码层面上会有一些小的改动,下面就告诉大家怎么去修改吧。 第一步…

算法笔记day07

目录 1.最长回文子串 2.买卖股票的最好时机(一) 3.过河卒 1.最长回文子串 最长回文子串_牛客题霸_牛客网 算法思路: 使用中心扩散算法,枚举所有的中点,向两边扩散,一个中点需要枚举两次,一次当回文串是奇数另一次回…

SpringBoot实现 License 认证(只校验有效期)

文章目录 一、License介绍二、授权者生成密钥对三、授权者生成license.lic证书3.1、 配置pom.xml3.2 、License生成类3.3 、License生成类需要的参数类3.4、自定义KeyStoreParam3.5、main方法生成license.lic注意事项 四、使用者配置4.1、配置pom.xml4.2、License校验类4.3、Li…

论文速读:YOLO-G,用于跨域目标检测的改进YOLO(Plos One 2023)

原文标题:YOLO-G: Improved YOLO for cross-domain object detection 中文标题:YOLO-G:用于跨域目标检测的改进YOLO 论文地址: 百度网盘 请输入提取码 提取码:z8h7 代码地址: GitHub - airy975924806/yolo…

ArkUI自定义TabBar组件

在ArkUI中的Tabs,通过页签进行内容视图切换的容器组件,每个页签对应一个内容视图。其中内容是图TabContent作为Tabs的自组件,通过给TabContent设置tabBar属性来自定义导航栏样式。现在我们就根据UI设计的效果图来实现下图效果: 根…

打包方式-jar和war的区别

1、jar包 JAR包是类的归档文件,与平台无关的文件格式,其实jar包就是java的类进行编译生成的class文件进行打包的压缩包。 JAR以ZIP文件格式为基础,与ZIP不同的是,JAR不仅用于压缩和发布,还用于部署和封装库、组件和插…

数据结构 ——— 数组栈oj题:有效括号

目录 题目要求 代码实现 题目要求 给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每…

【p2p、分布式,区块链笔记 Blockchain】truffle001 以太坊开发框架truffle初步实践

以下是通过truffle框架将智能合约部署到Ganache的步骤 Truffle简介环境准备:智能合约 编写 & 编译部署合约本地服务器ganache配置网络配置部署合约: 运行Truffle迁移(部署):与智能合约交互: 以下是通过truffle框架将智能合约部署到Ganach…

kaggle在线训练深度学习模型

kaggle https://www.kaggle.com/ code 通过jupyter notebook上传代码,执行训练 dataset 支持手动上传本地资源文件到input /kaggle/input,dataset通过input访问,input目录是只读的 /kaggle/working,保存文件到working&#…

网页中的滚动穿透

滚动穿透的现象 在开发中我们可以观察到这么一种现象,当用户在屏幕上某个可滚动区域滚动时,如果滚动到当前区域滚动边界时会带动其他区域进行滚动,直观表现是在进行博客评论时,滑动textarea会带动博客一起滑动,另一种…

智能汽车制造:海康NVR管理平台/工具EasyNVR多品牌NVR管理工具/设备实现无插件视频监控直播方案

一、背景介绍 近年来,随着网络在我国的普及和深化发展,企业的信息化建设不断深入,各行各业都加快了信息网络平台的建设,大多数单位已经或者正在铺设企业内部的计算机局域网。与此同时,网络也成为先进的新兴应用提供了…

【C++】一文带你深入理解C++异常机制

⭐️个人主页:小羊 ⭐️所属专栏:C 很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~ 目录 前言一、C语言处理错误的方式二、C异常三、异常的使用3.1 异常的抛出和捕获3.2 异常的重新抛出3.3 异常安全3.4 异常规范 四、自定义异…

NVR小程序接入平台/设备EasyNVR多品牌NVR管理工具/设备的多维拓展与灵活应用

在数字化安防时代,NVR批量管理软件/平台EasyNVR作为一种先进的视频监控系统设备,正逐步成为各个领域监控解决方案的首选。NVR批量管理软件/平台EasyNVR作为一款基于端-边-云一体化架构的国标视频融合云平台,凭借其部署简单轻量、功能多样、兼…

使用 pydub 的 AudioSegment 获取音频时长 - python 实现

通过使用 pydub 的 AudioSegment 获取音频时长,音频常用格式如 m4a,wav等。 安装 python 库: pip install pydub 获取 m4a 格式的音频时长代码如下,代码如下: #-*-coding:utf-8-*- # date:2024-10 # Author: DataBall - XIAN #…

sqli-labs靶场安装以及刷题记录-docker

sqli-labs靶场安装以及刷题记录-docker sqli-labs靶场安装-dockersqli-labs靶场刷题less-1 单引号less-2 数字型less-3 单引号括号less-4 双引号括号less-5 单引号布尔盲注less-6 双引号布尔盲注less-7 单引号加括号、输出到文件less-8 单引号布尔盲注less-9 单引号时间盲注les…

【移动应用开发】界面设计(二)实现水果列表页面

续上一篇博客 【移动应用开发】界面设计(一)实现登录页面-CSDN博客 目录 一、采用ViewBinding实现一个RecyclerView 1.1 在app/build.gradle中添加recyclerview依赖,并打开viewBinding (1)在app/build.gradle中添加…

基于Python+SQL Server2008实现(GUI)快递管理系统

快递业务管理系统的设计与实现 摘要: 着网络新零售的到来,传统物流在网购的洗礼下迅速蜕变,在这场以互联网为基础的时代变革中,哪家企业能率先转变其工作模式就能最先分得一杯羹,物流管理也不例外。传统的物流管理模式效率低下&a…

Git_GitLab

Git_GitLab 安装 服务器准备 安装包准备 编写安装脚本 初始化 GitLab 服务 启动 GitLab 服务 浏览器访问 GitLab GitLab 创建远程库 IDEA 集成 GitLab 安装 GitLab 插件 设置 GitLab 插件 安装 服务器准备 准备一个系统为 CentOS7 以上版本的服务器,使…

日常记录,使用springboot,vue2,easyexcel使实现字段的匹配导入

目前的需求是数据库字段固定,而excel的字段不固定,需要实现excel导入到一个数据库内。 首先是前端的字段匹配,显示数据库字段和表头字段 读取表头字段: 我这里实现的是监听器导入,需要新建一个listen类。 读Excel …