TCP协议原理一

news2024/11/16 0:41:37

在这里插入图片描述

文章目录

  • 一、TCP协议
  • 二、TCP工作机制
    • 1.确认应答
    • 2.超时重传
    • 3.连接管理
      • 三次握手
      • 四次挥手

一、TCP协议

我们的TCP协议相比于UDP协议复杂不少,今天我们就来一起学习一下TCP协议报文和原理
在这里插入图片描述
首先我们报头第一行里的端口号和UDP的端口号是一致的,都是用两个字节来表示。
32位序号和32位确认序号: 在这里先不给大家解释,等会我们再将TCP确认应答原理时会给大家讲到。
4位首部长度: 正是因为这个首部长度存在,我们的TCP的报头长度是可变的,而我们的UDP报头长度是8个字节固定死的,首先我们需要明白,我们选项之前的长度是固定的20字节,而我们首部长度可以调节的就是选项长度,我们首部长度的单位是4字节,选项长度等于首部长度 - 20字节,如果我们的首部长度是6,那么TCP报头就是24字节(选项相当于是4字节)。
**保留(6位): ** 我们这里的保留六位是为了以后扩展考虑的,因为我们的网络协议是一件成本较高的事情,就拿UDP来说,报文长度是2字节,因此一个包最大是64KB,如果我们想让它兼容更大一些的长度,理论可行但是实际操作极高,但是如果我们引入了保留字,我们后面TCP引入了新功能就可以使用这些保留字,不仅对报头结构影响极小,而且老设备也不需要升级也可兼容。
在这里插入图片描述
这个我们在后面讲原理的时候会介绍到。
16位窗口大小,16位紧急指针: 这些我们在后面会介绍到,16位窗口和我们的滑动窗口和流量控制原理有关。
16位校验和: 和我们的UDP校验原理相同,CRC,MD5,SHA1
选项: 选项(option),这个是对TCP一些功能扩展和TCP一些属性进行解释说明的。

TCP报文 = TCP报头 + TCP载荷(payload),载荷也就是我们的数据。

二、TCP工作机制

我们的TCP相比于UDP是一个比较复杂的协议,也包含很多机制,我们主要学习10大核心机制

1.确认应答

TCP的特点中有可靠传输的特性,确认应答就是实现可靠传输的核心机制。大家还需要明白,我们这里的可靠指的不是我们发送方百分百能将数据发送到接收方,而是尽可能的发过去即使没有发过去我们的发送方也能够知道。
比如我们有这样一个场景,一个宿舍中的A同学和B同学要通信。
在这里插入图片描述
我们这里的不上就称之为"应答报文",也叫ack(acknowledge).
当A同学收到不上的时候,就可以知道我们上号这个消息B同学已经看到了(证明没有丢包),如果我们一段时间后没有收到ack证明我们的消息大概率不见了(也就是丢包)。
TCP可靠传输主要就是靠这个确认应答机制来保证的,我们A给B发消息,B收到之后就会返回一个ack,A收到这个应答之后,就证明我们的数据顺利到达了(没有丢包)。
上述的通信是比较简单的单一通信,我们来看一个稍微复杂一点的。
在这里插入图片描述
同学A可能会连续发多条消息,发第二条消息时,不需要等待第一个消息的应答,我们的B同学收到消息立马回复,我们在网络通信时,很有可能发生后发先至,因为我们的网络环境是错综复杂的,很有可能发的晚的消息先到的情况。
上面的情况是正常的情况,那么我们来看一个不正常的情况。
在这里插入图片描述
因为这种后发先至的情况,我先收到了上,后收到了不上,这样我们的应答错乱后表示的含义就截然不同了。
首先网络上后发先至这种情况是客观存在无法避免的,我们应该考虑的是如何应对这种情况所带来的异义。
我们采取的办法是给传输的数据和应答报文编号。
在这里插入图片描述
当我们引入序号后,即使出现先发后至的情况,消息的顺序即使乱了,我们通过序号也可以明确将每条应答报文与其对应了。

在这里插入图片描述
我们任何一条数据(包括应答报文)都是有序号的,确认序号只有应答报文有,是否为应答报文取决于ACK这个标志位是否为1,如果为1证明是应答报文,如果是0表示不是应答报文。
我们实际上的TCP序号并不是简单的1,2这种方式编号,我们TCP是面向字节流的,我们的TCP序号也是按照字节来编号的。
在这里插入图片描述
假设我们的一条数据长度是1000个字节,我们的数据是由1开始的,此时我们第一个字节编号就是1,第二个字节编号就是2依次,但是我们前1000个字节都是属于同一TCP报文,因此我们TCP报头里记录的序号就是第一个字节的序号,也就是1。
当我们发送第二条数据,序号就是1001了,我们的TCP字节序号是依次增加的,起始字节序号是上一个数据的最后一个字节,我们TCP报头只需写TCP头一个字节序号即可,在根据TCP报文长度即可知道TCP的每一个字节的序号。
在这里插入图片描述
我们应答报文里的确认序号中的1001就是刚才尾字节1000基础+1的结果,1001所表示的含义有两个:
1.小于1001的数据都已经确认收到了
2.发送方接下来应该从1001这个序号开始发送数据

结论: TCP可靠传输最主要是通过确认应答机制保证的,我们不仅可以让发送方清楚的知道是否传输成功,并且通过序号和确认序号对多组数据进行了详细的区分。

2.超时重传

我们刚才在讨论确认应答的时候,只是在一个理想的传输场景下讨论的,那如果在传输过程丢包了呢?
首先丢包有两种情况: 1. 发送的数据丢了 2.应答报文ack丢了,站在我峨嵋你发送方的角度,这两种情况都认为是丢包了,正在因为这种丢包的可能性发送,我们TCP就引入了重传机制,我们在丢包的时候就要重新发一遍相同的数据,那么如何判断是丢包还是ack正在返回路上?
我们TCP直接引入一个时间阈值,在发送数据后,就会开始倒计时等待ack,如果时间超过时间阈值也没收到ack,统一认为丢包。
超时重传: 接收方在一定时间没有响应,发送方就重新发送一份相同的数据。
时间阈值: 超时时间具体是多少,这个我们不具体讨论是多少,根据场景业务而定,是可配置的。
在这里插入图片描述
这种情况比较形象,发送方发送的数据丢包了,在一定的时间后重新传输一次,然后收到ack之后就视为一次成功的传输。
在这里插入图片描述
但是当ack丢包时,对于我们主机B而言,1 -1000的数据接收了两次,这种情况就比较麻烦了,但是我们TCP对于重复的数据传输,具有去重功能,我们TCP存在一个发送缓冲区和接收缓冲区接收缓冲区相当于是接收方操作系统内核的一段内存,我们在网络编程的时候学习的socket的对象中都有一个接收缓冲区,我们主机B的网卡接收到数据之后,将数据放到主机soekct对象对应的接收缓冲区中,我们可以将这个缓冲区想象成一个优先级阻塞队列,我们根据序号可以将数据进行去重排序,如果有相同的数据就将后到的数据丢弃,排序就可以应对我们的后发先至情况。
结论: 由于我们去重与排序机制的存在,发送方只要发现在一定时间阈值内ack没有到达,就会重新发一份数据,数据即使重复乱序,我们的接收方都可以处理,去重和排序机制都依赖TCP报头的序号。
相信有一些善于思考同学又会问了,要是我们重传的数据有丢包了呢?
首先我们丢包是一件概率比较低的事件,连续重传丢包的概率更低,因此我们在重传到一定次数后,就不会再死磕,就会认为网络出现故障,TCP就会尝试重置连接,如果重置还是无效,就会彻底断开连接。
TCP的可靠传输: TCP的可靠传输通过 确认应答 和 超时重传机制保证的,两者相互配合,共同保证了TCP的可靠性。

3.连接管理

连接在不同的场景表示不同的含义,在我们TCP协议这里,表示的是维护一些信息(四元组)的空间。
在这里插入图片描述
我们TCP建立连接并不是指通过一根线将两者连接起来,而是将这两部分信息维护好,简单来说A要能通过这部分信息找到B,B能通过这部分信息找到B,我们称保存好这部分信息的空间为连接,删除这部分信息,称之为断开。

三次握手

我们仍然拿出A同学和B同学,刚上大学A同学和B同学想通过游戏加深一下感情,但是又不知道对方玩什么游戏,于是有了以下的场景:
在这里插入图片描述
首先A向B发出了询问,然后B回应了A,此时双方都知道了B玩王者农药,但想要一起组队玩王者农药,B需要明确A是否也玩,于是B又发送了一次请求,这时候A知道了B玩,B知道了A也玩,这个时候他们才能一起上号打游戏,相当于建立连接成功。
我们把上述过程的每次通信形象的称为一次挥手,但实际上我们有两次是可以合并成一次的。
在这里插入图片描述
我们所谓的三次握手的本质上是四次交互,双方各自需要发送一个建立的请求,然后收到一个ack,实际上是有四次的信息交互,但是中间两次是可以合并的,因此就构成了三次握手
如果不合并,可以吗?
不可以,如果我们从三次变成四次就会多封装分用一次,成本更高,就好比宿舍倒垃圾,本来可以一个大袋子一次性倒,一个是用两个小袋子分两次倒。

两次握手可以完成建立连接吗?
在这里插入图片描述
如果少了最后一次握手,站在A的角度,他已经知道了B玩王者农药,但是站在B的角度,他不知道A玩不玩王者农药。
有的同学可能会说,A能问你A肯定玩呀,虽然这个情况也有可能,但是TCP这里不适用,因为三次握手还有一个重要作用:验证通信双方各自的发送和接收能力是否正常
比如我们两个人在打王者农药,组队开麦,A和B能够顺利交流,需要有两个保证,就是A和B的麦和音响都是好的。
在这里插入图片描述
第一次通信,当B听到"你可以听到吗?" B知道了 A的麦是正常的,B的音响是正常的。 A什么都不知道。
第二次通信,当A听到"可以,你呢", B知道了A的麦是正常的,B的音响是正常的。A知道了A的麦和音响以及B的麦和音响都是正常的。
第二次通信之后,A以及知道了双方都满足了条件,但B知道的信息还不全,需要进行第三次通信。
第三次通信,当B听到"可以"时,证明我们A和B都知道了自己的麦和音响和对方的麦和音响是正常的,可以正常交流了。
三次握手的作用:
1.让通信双方建立相互的认可
2.验证双方的发送与接受能力是否正常
3.在握手的过程,双方协商一些参数。
在这里插入图片描述
我们客户端主动给服务器发送的建立连接请求称为SYN同步报文段.
在这里插入图片描述
在这里插入图片描述
这些都是TCP的状态,不同的TCP状态主要体现我们的TCP在干什么,三次握手中我们主要学习两个重要状态:
1.LISTEN服务器状态:表示我们的服务器以及转杯就绪,随时可以与客户端建立连接。
2.ESTABLISHED::这个状态我们客户端服务器都有,当我们进行两次握手后,我们的客户端就已经认为进行成功建立连接,于是进入了ESTABLISHED状态,我们的服务器只有当三次握手进行完毕后才认为成功的建立了连接,进入了ESTABLISHED状态,当我们成功建立连接之后就可以进行通信了。
上述描述的三次握手一次性记住不太容易,大家需要记住主要的流程:
在这里插入图片描述

四次挥手

握手和挥手都是形象的叫法,指的是客户端服务器之间的交互,四次挥手指的是通信双方给对方发一个断开连接的请求,在各自给对方一个回应。
这里我们同样是A同学和B同学打了一下午王者农药输了一下午:
在这里插入图片描述
这里需要注意,我们在断开连接的过程中,中间两次通常是不能合并的。
在这里插入图片描述
我们三次握手之所以中间两次可以合并,是因为它两是属于同一时机的,具体来说,三次握手的三次交互过程是系统内核完成的,服务器内核收到了syn之后会立即发送ack也会立即发送syn。
这就好比于我们在同一家店铺买东西,我们的三次握手中间的两次就相当于是同一时间段在一家店铺买的两样东西,所以可以通过一个包裹发送这两样东西,而我们四次挥手中间两次,则是在不同的天数买的,比如2月9号买了个牙刷,2月11买了个牙膏,则不能够通过一个包裹,必须通过两个包裹发送。
在这里插入图片描述
我们的FIN发起不是有内核控制的,而是我们客户端调用socket的close方法(进程退出)才会触发FIN,我们服务器的ack是有内核控制的,收到FIN之后立即返回ack,而我们服务器的FIN是我们服务器执行到socket的close方法(或进程退出)才会触发FIN。
因此大家注意到,我们服务器ack和FIN之间只有一个时间差的,而这个时间差的大小由我们的代码所决定,我们可以发开我们之前写的TCP客户端服务器回显服务器看一看。
在这里插入图片描述
我们可以看到这里的break决定着循环结束,而这里的break能够执行到取决于我们的hasNext为false,因就是流对象读到了EOF(文件结束标记),这里能读到EOF是因为内核收到了客户端发送来的FIN数据报,虽然我们的客户端程序没有显示的写close方法,但是当我们客户端进行退出的时候也会执行socket close会触发FIN。
在这里插入图片描述
当我们的循环执行结束之后,会执行到finally里的close方法,相当于我们服务器给客户端发送的FIN,我们上述代码里循环结束后立即FIN,ack与FIN之间的时间间隔相对就比较短,也就有可能包裹成一个,但是如果时间间隔比较长就不可以了,比如这样:
在这里插入图片描述
我们的代码在close之前进行了一系列操作,这样我们的FIN和ack时间间隔就比较久了,也就无法合并成一个了。
在这里插入图片描述
同样的我们断开连接中的FIN在报头中也有标志,FIN为1证明是断开连接的请求报文。
在这里插入图片描述
我们TCP四次挥手当中也有许多状态,我们这里重点学习两个TCP状态:
1.CLOSE_WAIT: 出现在被动连接的一方,等待关闭(等待socket调用close方法),大家需要注意的是,建立连接的过程中一定是客户端主动发起请求,断开连接可能是客户端也可能是服务器。
TIME_WAIT: 出现在主动发起断开请求的一方法,这里我们客户端是主动断开的一方,当客户端进行TIME_WAIT状态时,客户端认为四次挥手已经挥完了,这里的TIME_WAIT要保持TCP状态保持一会不要立即释放。
为什么我们的TIME_WAIT要等待一会不要立即释放连接?
因为我们最后一个ack虽然已经发出去了,但是仅仅是发出去了,到没到我们得打一个问号?万一这个ack丢包了呢,我们TIME_WAIT会在发完ack之后等,如果没有接收到重传的FIN,就认为最后一个ack没有丢包然后释放连接。
在这里插入图片描述
站在我们服务器角度来说,当我们ack发送了之后,进入TIME_WAIT状态时,相当于是四次挥手已经完成了一样,没有客户端的活了,虽然看起来完了,但是是建立在一切顺利的前提下,如果出现了丢包等情况,客户端就没有完成工作,我们的TIME_WAIT就是这些工作但的保证。
那么TIME_WAIT保持多久,才真正释放呢?
我们这里等待的时间为2MSL ,如果TIME_WAIT维持了2MSL都没用收到重传的FIN,就认为我们的ack顺利到达了。
那么MSL指的又是什么呢?
指的是,互联网上两个结点之间,消耗传输时间的最大时间。至于这个MSL通常大概是60s,在这里大家需要注意,我们这里的MSL无论如何定义都不可避免一些特殊情况,因此我们的MSL相当于是一个经验值,绝大多数情况下数据包传输时间都不会超过MSL。

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

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

相关文章

进大厂必备的Java面试八股文大全(2023最新精简易懂版,八股文中的八股文)

为什么同样是跳槽,有些人薪资能翻三倍?” 最近一个粉丝发出了灵魂拷问,类似的问题我收到过很多次,身边也确实有认识的同事、朋友们有非常成功的跳槽经历和收益,先说一个典型例子: 学弟小 A 工作一年半&am…

智云通CRM:买对了吗——大客户采购的方案实施

一旦采购合同签署后,供应商就要履行合同,按时交付产品进场使用,或实施服务方案。不过,无论对供应商还是客户来说,双方的合作并没有就此结束。 在这个阶段,客户会评估此次合作的供应商做事是否靠谱&#x…

Spring面试重点(四)——Spring事务

Spring事务 事务的方式 spring中使用事务有两种方式,一种是编程式事务,一种是声明式事务。编程式事务推荐使用TransactionTemplate,实现TransactionCallback接口,需要编码实现;声明式事务只需要在函数增加注解Transa…

【项目设计】—— 基于Boost库的搜索引擎

目录 前言 一、项目的相关背景 1. 什么是Boost库 2. 什么是搜索引擎 3. 为什么要做Boost搜索引擎 二、搜索引擎的宏观原理 三、搜索引擎技术栈和项目环境 四、正排索引 VS 倒排索引 —— 搜索引擎的具体原理 1. 正排索引(forword index) 2. 倒…

Linux tcpdump

tcpdump - 转储网络上的数据流 是不是感觉很懵?全方位描述tcpdump: 通俗:tcpdump是一个抓包工具,用于抓取网络中传输的数据包形象:tcpdump如同国家海关,凡是入境和出境的货物,海关都要抽样检查&#xff0…

新瑞鹏“狂飙”,宠物医疗是门好生意吗?

宠物看病比人还贵,正在让不少年轻一族陷入尴尬境地。在知乎上,有个高赞提问叫“你愿意花光积蓄,给宠物治病吗”,这个在老一辈人看来不可思议的魔幻选择,真实地发生在当下的年轻人身上。提问底下,有人表示自…

虹科分享 | 流浪地球背后:运载火箭行业的高性能计算!

当长征系列运载火箭直冲云霄时,你想到的是什么? 是嫦娥奔月,是技术革新,是一望无际的星空,是伟大的航天员 还是流浪地球中用火箭推进太空天梯的科幻场景 我 想到的是运载火箭行业背后的高性能计算 …… 是无数次的计算…

从写下第1个脚本到年薪30W,我的自动化测试心路历程

我希望我的故事能够激励现在的软件测试人,尤其是还坚持在做“点点点”的测试人。 你可能会有疑问:“我也能做到这一点的可能性有多大?”因此,我会尽量把自己做决定和思考的过程讲得更具体一些,并尽量体现更多细节。 …

vue3.0 响应式数据

目录1.什么是响应式2. 选项式 API 的响应式数据3.组合式 API 的响应式数据3.1 reactive() 函数3.2 toref() 函数3.3 toRefs() 函数3.4ref() 函数总结1.什么是响应式 这个术语在今天的各种编程讨论中经常出现,但人们说它的时候究竟是想表达什么意思呢?本质…

spark03-读取文件数据分区数量个数原理

代码val conf: SparkConf new SparkConf().setMaster("local").setAppName("wordcount")val sc: SparkContext new SparkContext(conf)val rdd: RDD[String] sc.textFile("datas/1.txt",2)rdd.saveAsTextFile("output")数据格式 &a…

Docker 部署微服务项目

目录 一、前言 二、环境准备 1、安装 Docker 2、Docker 安装 MySQL 3、Docker 安装 Redis 4、Docker 安装 Nacos 5、Docker 安装 Nginx 三、部署后端服务 四、部署前端服务 感谢观看!! 一、前言 以谷粒学苑为例,使用 Docker 部署后…

【SpringBoot3.0源码】启动流程源码解析 • 上

文章目录初始化SpringBoot启动类: SpringBootApplication public class AppRun {public static void main(String[] args) {SpringApplication.run(AppRun.class, args);} }步入SpringApplication.run(AppRun.class, args)方法: 这里分为两步&#xff1…

【暴力量化】查找最优均线

搜索逻辑 代码主要以支撑概率和压力概率来判断均线的优劣 判断为压力: 当日线与测试均线发生金叉或即将发生金叉后继续下行 判断为支撑: 当日线与测试均线发生死叉或即将发生死叉后继续上行 判断结果的天数: 小于6日均线,用金叉或…

Tensorflow中的多层感知器学习

Tensorflow中的多层感知器学习 在这篇文章中,我们将了解多层感知器的概念和它在Python中使用TensorFlow库的实现。 多层感知 多层感知也被称为MLP。它是完全连接的密集层,可以将任何输入维度转化为所需维度。多层感知是一个具有多层的神经网络。为了创…

【黑马SpringCloud(6)】Sentinel解决雪崩问题

微服务保护雪崩问题服务保护技术Sentinel微服务整合Sentinel流量控制簇点链路入门练习流控模式关联链路流控效果Warm Up排队等待热点参数限流隔离和降级FeignClient整合Sentinel线程隔离(舱壁模式)实现线程隔离熔断降级慢调用异常比例/异常数授权规则获取origin给网关添加请求头…

ROS2+nav2+激光雷达导航实践(上)

目录写在前面安装nav2nav2介绍nav2实践map地图保存地图读取状态估计(TF变换)所需TF坐标base_link -> sensor framesodom -> base_linkLaser Scan Matcher for ROS2map -> odomAMCL使用AMCL参数配置文件amcl_config.yaml效果过程中的知识点一、launch文件编写格式及方法…

Python 之 NumPy 切片索引和广播机制

文章目录一、切片和索引1. 一维数组2. 二维数组二、索引的高级操作1. 整数数组索引2. 布尔数组索引三、广播机制1. 广播机制规则2. 对于广播规则另一种简单理解一、切片和索引 ndarray 对象的内容可以通过索引或切片来访问和修改(),与 Pytho…

30、基于51单片机交通灯车流量管控数码管显示系统设计

摘要 随着社会主义的建设,城市的规模在不断扩大,城市的交通也在不断的提高和改进,交通的顺畅已经成为制约社会主义建设的一个重要因素。目前,伴随着机动车辆的不断增加,尤其是十字路口的交通建设 颇为关键&#xff0c…

PID控制算法简介

目录 1 简介 2 比例Proportional 3 积分Integral 4 微分Differential 5 公式 6 积分限幅 7 积分限行 8 相关代码 1 简介 PID控制中有P、I、D三个参数,PID即:Proportional(比例)、Integral(积分&#…

【渝偲医药】实验室关于核磁共振波谱NMR的知识(原理、用途、分析、问题)

核磁共振波谱法(Nuclear Magnetic Resonance,简写为NMR)与紫外吸收光谱、红外吸收光谱、质谱被人们称为“四谱",是对各种有机和无机物的成分、结构进行定性分析的强有力的工具之一,亦可进行定量分析。 核磁共振&…