【计算机网络】面试必问TCP十大机制

  1. TCP协议的报文格式

  说明:

  TCP 报文格式主要分为两部分:TCP 报文头部和数据部分。以下是对各字段的详细解释:

TCP 报文头部

  • 源/目的端口:各占用16位。表示数据从哪个进程发送,发送到哪个进程去。
  • 序号字段:占 32 位。用于标识发送端发送的字节流中的每一个字节的顺序编号。
  • 确认序号:占 32 位。表示接收端期望接收的下一个字节的序号,是对发送端的一种确认机制。例如,接收端收到序号为 1000 到 1999 的数据段后,发送的确认报文中确认序号字段的值应为 2000,表示已成功接收到 1000 到 1999 字节,期望下一个字节为 2000。
  • 首部长度:占 4 个字节。表示 TCP 报文头部的长度。 保留字段:占 6 位。为 TCP 将来的发展预留空间,目前必须全部为 0。
  •  标志字段:占 6 位,包含六个控制位:
  • URG:当 URG = 1 时,表示紧急指针字段有效,用于指示紧急数据。紧急数据可以绕过正常的数据流,优先传输和处理。
  •  ACK:当 ACK = 1 时,表示确认序号字段有效。在 TCP 建立连接后,ACK 标志位通常为 1,表示对收到的数据进行确认。
  •  PSH:当 PSH = 1 时,表示接收端应立即将数据交付给上层应用,而不要等到整个缓存都填满了之后再向上交付。
  • RST:当 RST = 1 时,表示连接出现严重差错,必须释放连接,然后再重新建立传输连接。
  •  SYN:在建立连接时使用,当 SYN = 1 而 ACK = 0 时,表示这是一个连接请求报文段;对方若同意建立连接,在发回的报文段中使 SYN = 1 和 ACK = 1。
  • FIN:当 FIN = 1 时,表示发送端的数据已发送完毕,请求释放传输连接。 
  • 窗口大小:占 16 位。用于流量控制,表示接收端可接收的数据量,以字节为单位。发送端根据窗口大小调整发送的数据量,以避免接收端缓冲区溢出。
  •  检验和:占 16 位。用于确保数据的完整性。发送端计算并填充检验和字段,接收端收到报文后再进行计算,比较结果是否一致。如果不一致,表示数据在传输过程中发生了错误。 
  • 紧急指针:占 16 位。仅在 URG 标志置 1 时有效,指示在报文中的紧急数据的结束位置。

  2. 数据部分:可变长度,包含上层应用程序的数据。TCP 头部后面的数据部分是上层应用程序传递给 TCP 的数据,例如网页内容、文件数据等。

  1. 可靠传输机制

  注意:可靠并不意味着消息能够百分之百发给接收方,而是尽可能的把消息传输过去,即使没有成功发送,最气码发送方要能够知道。

 确认应答机制

  确认应答机制是保障TCP可靠传输最核心的机制之一。主机A给主机B发了个消息,主机B收到消息之后,就会给主机A返回一个应答报文(ACK),此时,主机A收到应答之后,就知道自己发送的数据已经成功到达主机B了。如下图所示:

  网络环境十分复杂,可能会出现后发先至的情况。如下图所示:

  说明:此处我可能连续发送多条消息,我发第二条消息的时候,不需要等待第一个消息的回应,女神收到消息之后立马就会回复我。在这次网络通信中,原本的意思是这样的:我说:女神女神我请你吃麻辣烫好不好;女神说:好啊好啊;我说:女神可以做我女朋友吗?女神说:滚蛋。此时引发了歧义。

  结论:网络出现后发先至的现象是客观存在的,无法避免的,因此,应答报文(ACK)到达的顺序也是有可能发生变化的。此时就要考虑如何规避这种顺序错乱带来的歧义。

  解决后发先至的方案:给传输的数据和应答报文都进行编号。如下图所示:

  当引入序号之后,此时就不怕顺序乱了;即使顺序乱了,也可以通过序号来判断当前应答报文是针对哪个数据进行的。  

  注意:上图中的1,2只是为了说明可以采取编号的方式来解决后发先至的问题,TCP的序号并不是按照1,2来编号的,而是按照字节来编号。

  主机A给主机B发送一个数据报,主机B要返回一个确认应答的数据报给主机A 。
实现的方式:序号和确认序号保证了响应应答针对的是哪一条消息的应答。

  说明:

  1:主机A发送的数据是基于TCP报头中的 " 32位序号 "来保存的,一个字节对应一个序号。

  2:确认应答的数据是基于TCP报头中的 " 32位确认序号 " 来保存的,此时,ACK标志位为1。

  3:确认序号的取值,是收到的数据的最后一个字节的序号 + 1。

  4:接收者返回确认序号,说明该确认序号之前的数据被接收者全部接收到。

  小结:TCP可靠传输的能力,最主要通过确认应答机制来保证的,通过应答报文,就可以让发送方清楚的知道数据传输是否成功。进一步的引入了序号和确认序号。


 

 超时重传机制

  讨论确认应答的时候,只是讨论了顺利传输的情况,如果丢包了呢?

  丢包分为两种情况:一种是发送端发送的数据没有到达接收端,一种是ACK丢了。因此,TCP引入了重传机制,在丢包的情况下,发送端就需要重新发送数据报。

  这次传输到底是丢包了,还是ACK走得慢,还在路上呢?针对这一问题,TCP引入了一个时间阈值,发送方发了一个数据之后,就会等待ACK,开始计时,如果在时间阈值内,还没有收到ACK,此时不管ACK是丢了,还是在路上,都统一认为是丢包了。

  

  网络环境十分复杂,可能存在丢包情况,超过一定时间,主机A还没有收到ACK,主机A就需要重新发送数据报。

  数据丢了的情况:如下图所示:

   ACK丢了的情况:如下图所示:

  问题:对于主机B来说1-2000就收到了两次,重复的数据怎么办?

  TCP对于这种重复数据的传输,会进行去重处理。TCP存在一个接收缓冲区(是一个存储空间,接收方操作系统内核里的一段内存),主机B收到主机A的数据,其实就是主机B的网卡读到了数据,然后把这个数据放到主机B对应的接收缓冲区中;此时根据数据序号,TCP很容易识别当前接收缓冲区里的这两条数据是否是重复的。如果重复,直接把后来的这份数据直接丢弃;保证应用程序进行read操作的时候,数据一定是不重复的。

  问题:如果重传的数据丢了,该怎么办?

  丢包本就是一件小概率事件,此时重传的数据也发生了丢包,概率更小,TCP如果进行重传多次依然丢包,此时网络势必出现了重大故障。

  小结1:

  由于去重和重新排序机制的存在,发送方只要发现ACK没有按时到达,就会重传数据。即使重复了,顺序乱了,接收方都能够进行有效的处理。(去重和排序都依赖于TCP报头的序号)。

  小结2:

  可靠传输是TCP最核心的部分,TCP可靠传输就是通过确实应答和超时重传来进行体现的,其中确认应答描述的是数据顺利传输的情况;超时重传描述的是传输出现问题的情况;两者相互配合,共同支撑整体的TCP可靠性。

连接管理机制(三次握手,四次挥手)

  在发送数据之前,要先通过三次握手建立连接;不需要发送数据了,通过四次挥手断开连接。

  建立连接(三次握手):通信双方各自要记录对方的信息,彼此之间要相互认同。

  如图所示:

   说明:

  1:客户端向服务端发送SYN,申请建立连接。
  2:服务端返回ACK(第一次SYN的应答)和SYN,申请建立客户端到服务端的连接。
  3:客户端收到数据,TCP状态设置为ESTABLISHED,表示两端连接建立完成,并且发ACK。      4:服务端收到数据,状态置为ESTABLISHED,表示接收端到发送端的连接建立完成。

  小结:

  所谓的三次握手,本质上是四次交互。通信双方,各自要向对方发起一个建立连接的请求,同时,在各自向对方回应一个ACK,进行了四次交互。中间的两次交互,是可以合并成一次交互的,因此构成了三次握手。

  问题:中间这两次交互,不合并可以吗?

  一定要进行合并。封装分用两次,成本比一次高。

  问题:三次握手中的中间两次为什么可以合并?四次挥手就不行呢?

  三次握手能够合并,因为中间这两次属于同一时机触发。三次握手在交互过程中,是在纯内核中完成的,服务器的系统内核收到客户端的syn之后,就会立即发送ack和syn。

  结论:三次握手主要是为了检查当前网络状况是否满足可靠传输的基本条件,同时也是在检测通信双方的发送能力和接收能力是否正常 。

四次挥手 

  说明:

  1:客户端发送FIN到服务端,申请关闭客户端到服务端的连接。

  2:服务端收到FIN状态置为CLOSE_WAIT,并返回ACK。

  3:服务端发送FIN到客户端,申请关闭服务端到客户端的连接(服务端程序执行socket.close)

  4:客户端收到FIN返回ACK应答,并进入TIME_WAIT时间等待状态,客户端等待一段时间后,状态置为CLOSED,服务端收到应答后,状态置为CLOSED。

思考:

  为什么服务端不将ACK和FIN合并一起发送,形成三次挥手呢?
  答:主要是ACK和FIN的发送时机不同,ACK是操作系统内核响应的(立即执行),而此时服务端还可能在继续发送数据,待处理完数据后由程序调用close方法后才发送FIN。

  为什么客户端要等待一段时间(TIME_WAIT)状态才置为CLOSED,而不直接将状态置为CLOSED?

  答:如果客户端给服务端的ACK丢包后,服务端得重新给客户端发送FIN,此时客户端给服务端ACK,所以此时状态不能置为CLOSED,得等待一段时间(2MSL,MSL为网络上任意两点传输的最大时间)确保服务端收到客户端的应答 。(如果最后一个ACK丢了,站在服务器的视角来看,服务器不知道是对方的ACK丢了,还是自己发的FIN丢了,此时统一视为FIN丢了,需要进行重传处理。既然服务器可能需要重传FIN,客户端就需要针对这个重传的FIN进行ACK响应;如果彻底把连接释放了,这样ACK就无法进行了,因此使用TIME_WAIT状态保留一定的时间,就是为了能够处理最后一个ACK丢包的情况,能够在收到重传的FIN之后,进行ACK响应。)。

滑动窗口

  对于基本确认应答的的情况来说,每次发送一个数据,都需要等待ACK到了再发下一个。

  如图所示:

  滑动窗口的本质就是不等待的批量发送一组数据,然后用一份时间来等待一组数据的多个ACK。如图所示:

  把不需要等待,就能直接发送的数据的最大的量,称为窗口大小。在这个图中窗口大小是4000。

  注意:当批量发送了窗口大小数据之后,发送方就要等待ACK了,需要注意的是,不是等待所有ACK到达,才继续往下发,而是等待到一个ACK,就继续往下发一条数据。 

  如图所示:

如果出现了丢包,如何确保可靠传输?

  • 情况一:数据已经收到,返回的ACK丢包

  部分ACK丢了不要紧,因为可以通过其他的确认序号进行确认 。

  • 情况二:发送数据的时候就已经丢包  

  对这个图进行说明:由于1001-2000的数据丢包了,接下来的2001-3000到达主机B之后,B给A返回的ACK确认序号仍然是1001,这个1001的含义可以理解为,B向A在索要1001之前的数据;此时A重新发送1-1000的数据给B,发送成功了,此时B给A发送7001。(这个7001可以从两个角度去理解:1:B告诉A7001之前的数据我已经收到。2:B告诉A,你接下来发送的数据应该是7001-8000)。 

  上述重传的方式叫做快速重传(只重传丢失的数据),这个快速重传可以视为是超时重传机制在滑动窗口下的变形。如果当前传输的数据密集,按照滑动窗口的方式来传输,此时按照快速重传来处理丢包;如果当前传输的数据稀疏,按照超时重传机制进行处理。

流量控制 

  流量控制是一种干预发送窗口大小的机制。一般来说,窗口越大,传输的效率就越高(一份时间等到的ACK就越多),但是窗口也不能无限大。原因如下:

1.完全不等待ack,可靠性不能得到保障。

2.窗口太大,会消耗太多的系统资源。

3.发送速度太快,接收方处理不过来。

  接收方的处理能力,是一个很重要的约束依据,发送方发送数据的速度,不能超出接收方的处理能力。流量控制需要做的工作就是,根据接收方的处理能力,协调发送方的发送速率。

如何衡量接收方的处理能力?

 

  解释说明:TCP中采用接收缓冲区里的剩余容量作为衡量发送方发送速率的指标。每次主机A给主机B发送了数据之后,主机B就需要计算一下自己的接收缓冲区里的剩余空间,然后把这个值通过ack报文返回给主机A;主机A根据这个值来决定接下来发送的速率是多少(窗口大小)。

  注意:由于接收方的接收缓冲区剩余空间是一直在动态变化的,所以每次返回ack带回来的数值(窗口大小)都在变化,发送方也就在动态的调整自己的发送速率。当窗口大小为0,发送方就要暂停发送,暂停发送的等待过程中,会给B定期发送窗口探测报文,这个报文不携带具体的业务数据,只是为了触发ack查询窗口大小。如下图所示:

拥塞控制

  流量控制和拥塞控制共同决定发送方的窗口大小是多少。流量控制考虑的是接收方的处理能力;拥塞控制描述的是传输过程中中间节点的处理能力。

如图所示:

  在前面,我们讨论了接收方的处理能力,和发送方的发送速率,但没有讨论中间节点,那么怎么去衡量中间节点对数据的处理能力呢?

  中间节点的处理能力不好量化,TCP中采取的策略是通过试验的方式,来测试出一个合理的值。

如图所示:

解释说明:

  从第0轮开始,窗口大小是一个单位,发现传输的数据没有丢包,就扩大窗口。第一轮2,第二轮4,第三轮8......依次类推,成指数级增长的状态;当增长速率达到阈值之后,从指数增长变成线性增长,增长的前提是不丢包。在接下来,当传输过程中一旦丢包,说明此时发送的速率已经接近网络的极限了。 此时就把窗口大小一下缩成很小的值,在重复指数增长和线性增长的过程。

意义:

  拥塞窗口不是一个固定的数值,而是一直动态变化,随着时间的推移,逐渐达到一个动态平衡的过程,这样做既把问题解决了,同时随着网络的动态的变化而动态变化。拥塞控制和流量控制的窗口,共同决定了发送方实际的发送窗口。

延时应答

  延时应答就是主机B收到数据之后,不要立即返回ACK,而是稍微等一会在返回。在等待的时间里,接收方的应用程序,就能把接收缓冲区的数据先处理一下,这样接收缓冲区的空间就大了一点。延时应答要做的的就是,在接收方能处理得了的前提下,尽可能的把窗口放大一点。

如图所示:

解释说明:

  延时应答采取的策略:在滑动窗口下,ack不在每一条数据都返回,此处是隔一条返回一个ack。

捎带应答 

  为了提高效率,在延时应答的基础之上引入捎带应答。客户端服务器最典型的模型就是"一问一答",如下图所示:

解释说明:

  B返回的ack和B业务上的响应,它们属于不同时机。由于TCP存在延时应答机制,就导致等待ack的过程中,B就要给A发送业务数据了,此时,就可以让业务数据捎上这个ack一起返回给A。

  本来是不同时机,在延时应答的作用下,可能就成为相同的时机,此时就会合并,如图所示:

粘包问题

  TCP是面向字节流的,一次读取一个字节,多个字节都是可以的。这样势必会导致一次读到的数据,可能是半个应用层数据报,可能是一个应用层数据报,也可能是多个应用层数据报。

解决方案:

1:约定好分隔符。

2:约定每个包的长度。 

异常情况

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

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

相关文章

千古风流人物 陆游

简介 陆游(1125年-1210年),字务观,号放翁,越州山阴(今浙江绍兴)人,南宋诗人、词人。后人每以陆游为南宋诗人之冠。是中国南宋时期的著名文学家、词人、政治家和军事家。 陆游出生在…

基于SpringBoot+Vue+MySQL的药品信息管理系统

系统展示 管理员界面 医生界面 员工界面 系统背景 随着医疗技术的不断提升,药品在治疗疾病中扮演着越来越重要的角色。传统的药品管理方式以人工方式为主,但人工管理难以满足现代社会快速发展的需求。因此,需要一种更加高效、便捷的信息化管理…

FLORR.IO画廊(2)

指南针(超级) 是Florr.io的一种辅助花瓣,用于指示超级生物的位置。 基础(超级) 是florr.io的一种攻击型花瓣,玩家在初次游玩时即获得5个基本,个数不随着等级改变而改变,基本不可合成…

C++之模版进阶篇

目录 前言 1.非类型模版参数 2.模版的特化 2.1概念 2.2函数模版特化 2.3 类模板特化 2.3.1 全特化和偏特化 2.3.2类模版特化应用实例 3.模版分离编译 3.1 什么是分离编译 3.2 模板的分离编译 3.3 解决方法 4. 模板总结 结束语 前言 在模版初阶我们学习了函数模版和类…

erlang学习:Linux命令学习9

sed命令介绍 sed全称是:Stream EDitor(流编辑器) Linux sed 命令是利用脚本来处理文本文件,sed 可依照脚本的指令来处理、编辑文本文件。Sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等 sed 的运行…

四川全寄宿自闭症学校专业团队详解

在广州市的一隅,有一所名为星贝育园的特殊教育学校,它远离城市的喧嚣与纷扰,为自闭症儿童提供了一个宁静、安全的学习与生活环境。这所学校致力于通过全方位的教育和照顾,帮助自闭症儿童在这个充满挑战的世界中寻找到属于自己的快…

【C++】—— 继承(上)

【C】—— 继承(上) 1 继承的概念与定义1.1 继承的概念1.2 继承定义1.2.1 定义格式1.2.2 继承父类成员访问方式的变化 1.3 继承类模板 2 父类和子类对象赋值兼容转换3 继承中的作用域3.1 隐藏规则3.2 例题 4 子类的默认成员函数4.1 构造函数4.1.1 父类有…

Oracle 11g RAC 节点异常重启问题分析

一、背景 在国庆期间巡检的时候,发现数据库alert日志中出现了异常重启的信息,当即对该报错进行分析处理。 二、处理过程 (1)数据库告警日志分析 node1 alert: Sat Oct 05 13:05:14 2024 Thread 1 advanced to log …

【光追模组】使命召唤7黑色行动光追mod,调色并修改光影,并且支持光追效果,游戏画质大提升

大家好,今天小编我给大家继续引入一款游戏mod,这次这个模组主要是针对使命召唤7黑色行动进行修改,如果你觉得游戏本身光影有缺陷,觉得游戏色彩有点失真的话,或者说你想让使命召唤7这款游戏增加对光线追踪的支持的话&am…

75 华三vlan端口隔离

华三vlan端口隔离 为了实现端口间的二层隔离,可以将不同的端口加入不同的VLAN,但VLAN资源有限。采用端口隔离特性,用户只需要将端口加入到隔离组中,就可以实现隔离组内端口之间二层隔离,而不关心这些端口所属VLAN&…

剖析 Redis:应对雪崩、穿透和击穿的实战秘籍

前言 用户的数据通常存储在数据库中,而数据库的数据存放在磁盘上。 磁盘的读写速度在计算机硬件中可以说是最慢的。 如果用户的所有请求都直接访问数据库,当请求数量增多时,数据库很容易崩溃。因此,为了避免用户直接访问数据库&a…

Java垃圾回收简述

什么是Java的垃圾回收? 自动管理内存的机制,负责自动释放不再被程序引用的对象所占用的内存。 怎么触发垃圾回收? 内存不足时:JVM检测到堆内存不足时,无法为新的对象分配内存时,会自动触发垃圾回收。手动…

Pandas -----------------------基础知识(八)

Pandas内置Matplotlib 加载数据 import pandas as pdanscombe pd.read_csv(/root/pandas_code_ling/data/e_anscombe.csv) anscombe dataset_1 anscombe[anscombe[dataset]I] dataset_1dataset_1.describe() 提供数据 dataset_1 anscombe[anscombe[dataset]I] dataset_2 an…

【C语言】分支和循环(2)

🤔个人主页: 起名字真南 😙个人专栏:【数据结构初阶】 【C语言】 【C】 目录 1 关系操作符2 条件操作符3 逻辑操作符 :|| ,&& ,!3.1 逻辑取反运算符3.2 与运算符3.3 或运算符3.4 练习闰年判断3.5 短…

仪器校准机构不符合项应该怎么签发和整改?

签发不合格项是内审工作之中非常重要的一环,那么如何正确签发不合格项,下列几个方面可以供大家参考: 一、目的 为便于仪器校准机构正确理解不符合项整改要求,特制定本指南,以指导企业规范、有效、高效地处理不符合项。…

旅游管理智能化:SpringBoot框架的应用

第一章 绪论 1.1 研究现状 时代的发展,我们迎来了数字化信息时代,它正在渐渐的改变着人们的工作、学习以及娱乐方式。计算机网络,Internet扮演着越来越重要的角色,人们已经离不开网络了,大量的图片、文字、视频冲击着我…

SpringBoot教程(二十四) | SpringBoot实现分布式定时任务之Quartz

SpringBoot教程(二十四) | SpringBoot实现分布式定时任务之Quartz 简介适用场景Quartz核心概念Quartz 存储方式Quartz 版本类型引入相关依赖方式一:内存方式(MEMORY)存储实现定时任务1. 定义任务类2. 定义任务描述及创建任务触发器3. Quartz的…

强引用、软引用、弱引用、虚引用用法

强引用、软引用、弱引用、虚引用用法 强引用弱引用弱引用虚引用 强引用 强引用是指程序中在程序代码之中类似“Object obj new Object()”的引用关系,无论任何情况下,只要强引用关系还存在,垃圾回收器就不会回收掉被引用的对象。 强引用是我…

日期类(Date)的实现 (C++版)

​ 🌹个人主页🌹:喜欢草莓熊的bear 🌹专栏🌹:C入门 目录 前言 一、Date的头文件,包含函数声明 二、 Date.cpp 2.1 int GetMonthDay(int year, int month) 2.2 bool Check() 2.3 Date& …

【吊打面试官系列-MySQL面试题】什么是基本表?什么是视图?

大家好,我是锋哥。今天分享关于【什么是基本表?什么是视图?】面试题,希望对大家有帮助; 什么是基本表?什么是视图? 基本表是本身独立存在的表,在 SQL 中一个关系就对应一个表。 视图…