TCP协议内部工作机制一(确认应答,超时重传,连接管理)

news/2024/11/24 1:41:06/

目录

TCP报文结构

TCP的首部长度

保留(6位)

TCP特点

TCP内部的工作机制

一确认应答

超时重传

连接管理

建立建立(三次握手)

 TCP断开连接(四次挥手)


TCP报文结构

 TCP的报文结构中,16位源端口,16位目的端口,16位校验和和UDP是一样的,本篇文章就暂不介绍了,可参考俺之前写的UDP协议详解,

TCP的首部长度

TCP的首部长度是指TCP的报头长度,TCP报头的长度是可变的,因为在TCP报头中有选项这一栏,它是可有可无的,如果不加选项TCP报头是固定长度20字节,因此我们也可以算出选项长度:报头长度-20字节.另外注意4位首部长度4个bite位,范围是0->15,单位是4字节,也就是说如果4位首部长度显示的是5,说明这个报头没有加选项,如果4位首部长度是6,说明报头一共24个字节,选项长度为4字节.

保留(6位)

此处TCP的6位保留位为了以后TCP扩展用的,方便以后扩展升级,给报头添加一些新的部分,就可以直接拿这些保留位就好了


其它部分会在接下来的TCP协议工作原理中介绍.

TCP特点

有连接,可靠,面向字节流,全双工

TCP内部的工作机制

一确认应答

确认应答是TCP实现可靠传输最核心机制,可靠传输不是说把消息100%发送给对方(由于网络物理等因素干扰,不可能实现),而是,当我们成功把数据发送给对方,我们知道发送成功了,当我们没有把数据发送给对方,我们能知道发送失败了

简单来说就是A给B发了个消息,B收到后就会返回一个应答报文(ack),此时A收到应答后,就知道刚刚发的数据已经顺利发送给了B

序号和确认序号

 

 同样我给hxd发消息,但是我可能是连续发俩条消息,我发第二天消息的时候没有等第一条消息的ack,hxd收到我的消息就立即回应

 此时就可能产生歧义,站在我的视角来看,我说走,上号,hxd的回答是滚犊子,我说"我是恁爹",hxd的回答是好啊,好啊.

由于网络俩个主机之间路线有多条,数据报1数据报2走的可能是不同的路线,数据报1的转发路径上的路由器/交换机和数据报2的路由器/交换机可能不一样,有的转发速率快,有的转发速率慢,此时俩个数据报到达的顺序可能就发生改变,就可能会发生后发先至这种情况!此时我们就需要考虑如何规避这种顺序错乱带来的歧义.

 当我们使用序号确认序号,就不怕顺序错乱了,即使顺序错乱,因为有序号和确认序号我们也不会产生歧义

任何一条数据(包括应答报文)都是有序号的,确认序号只有应答报文有(普通报文确认序号字段无意义),如果上面的报文结构图中ACK显示的是1,则表示是应答报文,如果是0,则表示不是应答报文

TCP的序号是面向字节流的,TCP的序号是按照字节来编号的

总结,我们通过确认应答机制,通过应答报文来让发送发知道传输是否成功,进一步引入序号和确认序号,针对多组数据进行区分

超时重传

如果我们发送的数据,丢包(发送发发给接受方的数据丢了)了怎么办? 

丢包分为俩种情况,1是发送方发送的数据丢了,2是接受方返回的应答报文(ack)丢了,这俩种情况,在发送方的视角是分不清的,得到的结果都是发送方没有收到接受方的应答报文.所以发送方都会认为是发送的数据丢了

此时就会有TCP的重传机制,TCP有一个时间阈值,发送方发了一个数据后,就会等待ACK,此时开始计时,如果在时间阈值范围内没有收到ACK,就认为是丢包了,就会重新给接受方发送数据

当然,对于接收方发送返回的应答报文丢了,发送方重新发送数据.此时接收方就收到了2份同样的数据,这种情况会有特殊处理(如果不处理,就可能会发生一个支付请求,支付俩次这种情况),TCP存在一个"接受缓冲区"这样的存储空间(接收方操作系统内核里的一段内存),每个TCP,socket对象,都有一个接收缓存区(也有一个发送缓冲区),主机B收到主机A的数据,其实B的网卡已经读到数据了,把这个数据放到B对应的socket的接收缓冲区中(此处的接收缓冲区就相当于是一个阻塞队列),根据数据的序号,TCP很容易识别当前的俩条数据是否重复,如果重复就把后来的这份重复的数据丢了,这样就保证read读到的数据,一定是不重复

总结:由于接收缓冲区序号的存在(接收的数据都是先放在接收缓冲区的,如果发生后发先至也没关系,由于序号的存在,我们很容易接收缓冲区给数据重新排序去重),即使数据重复了,顺序错乱了,接收方也能很好的处理.        

重传的数据是否可能又丢包了?这是有可能的,因此超时重传可能会重传N次,当然N不会是一个很大的数字,当重传几次都丢包,此时再重传意义也不大了.(很可能是因为网络出现重大故障).因此当重传到一定次数后,此时就不会重传了,视为网络出现故障,接下来TCP会尝试重置连接(相当于断开连接,重连),如果还是失败,就彻底断开连接了,另外重传的时候,第一重传的时间间隔和第二次重传的时间间隔不一样,重传的轮次越大,间隔越大

TCP的可靠传输就是通过 确认应答 + 超时重传 来体现的,其中确认应答描述的是传输顺利的情况,超时重传描述的是传输出现问题的情况 

连接管理

TCP建立连接
A和B建立连接,A中就有一部分存储空间存储了B的IP和端口,B中也有一部分空间存储了A的IP和端口,这俩部分信息被维护好了,此时A和B就建立了连接,而保存这部分信息的储存空间(数据结构)也称为 连接

TCP断开连接

A和B把自己储存的连接信息删了,此时就称为断开连接

那我们是如何具体的建立连接 和 断开连接的呢?

建立建立(三次握手)

通信双方需要各自记录对方的信息,彼此之间相互认同

SYN:客户端服务器发起的建立连接请求称为SYN,也叫同步报文段

这里为什么要把中间俩次的响应和请求合并到一起?

这俩次交互的时机相同,都是操作系统内核收到建立连接请求的时候,返回响应的同时也会给对方发送一个建立连接的请求 .另外,每次交互都需要封装和分用,交互成本很高,我把俩次交互合并成一次这样只用分装分用一次就可以了.

俩次握手能否完成建立连接的过程?

如果只有俩次,比如这里最后A没有给B返回一个ACK,在A的视角是可以的,知道了A保存至了B的信息,并且知道B保存了自己的信息,但在B的视角,B只知道自己保存了A的信息,但不知道A是否保存了自己的信息.另外三次握手还有个作用是,验证通信双方各自的发送能力和接收能力是否正常,如果是俩次握手,B是不知道自己的发送能力是否正常的

三次握手的意义:

1.让通信双方各自建立对对方的"认同"(保存了对方的信息)

2.验证通信双方各自的接收能力和发送能力

3.在握手的过程中,双方来协商一些重要参数

TCP在建立连接阶段的俩个状态

1.LISTEN
服务器的状态,表示服务器已经准备就绪,随时可以有客户端来建立连接

2.ESTABLISHED
客户端服务器都有的状态,表示连接建立完成,接下来可以正常通信了

 TCP断开连接(四次挥手)

四次挥手和三次握手类似,都是通信双方向对方发起一个断开连接的请求,再各自给对方一个回应

 这里四次挥手能不能变成三次挥手呢(中间的ACK和FIN能不能合并)

不能,FIN的发起不是由内核控制的,而是由应用程序调用socket的close方法(或者进程退出)才会触发FIN.ACK则是,当收到FIN,操作系统内核就会立即返回一个ACK,所以FINACK发送的时机不同,这俩者之间会有一个时间差,服务器的程序执行到了对应的close方法才会触发FIN.当然如果执行程序执行close刚好和返回ACK的时机一样,此时也是可以合并的

TCP在断开连接阶段的俩个状态

1.CLOSE_WAIT
出现在被动断开连接的一方,表示等待关闭(等待调用close方法关闭socket)

2.TIME_WAIT
出现在主动发起断开连接的一方,假设是A是主动断开的一方,当A进入TIME_WAIT,相当于四次挥手已经挥完了.此时这里的TIME_WAIT要保持当前的TCP连接状态,不要立即释放.因为此时最后一个ACK刚刚发出去,还不确定有没有丢包,因此TIME_WAIT会等一段时间,之后如果没有收到重传的FIN,就认为最后一个ACK没有丢包,就彻底释放连接了(如果这里不保持连接状态,立即释放,如果最后一个ACK丢包了,连接断了,B是没法向A重传FIN的).TIME_WAIT会保持2MSL,意思是A如果经历了2MSL这个时间还没有收到重传的FIN,就认为这个ACK正常到达了(B没有重传FIN),MSL指的是,互联网上任意俩个节点数据传输消耗的最大时间,通常情况下这个值是60s


http://www.ppmy.cn/news/43582.html

相关文章

Android---内存泄漏检测核心原理

目录 LeakCanary 核心原理 LeakCanary 检测对象的类型 ReferenceQueue 与 WeakReference LeakCanary 里的监控列表与保留列表 常见内存泄漏案例 1. 单例导致内存泄漏 2. 静态变量导致内存泄漏 3. 非静态内部类导致内存泄漏 4. 未取消注册或回调导致内存泄漏 5. Timer…

jenkins gitlab asp.net core持续集成

什么是jenkins Jenkins直接取自其官方文档,是一个独立的开源自动化服务器,您可以使用它来自动执行与构建、测试、交付或部署软件相关的各种任务。 jenkins可以干什么 Jenkins 通过自动执行某些脚本来生成部署所需的文件来工作。这些脚本称为JenkinsFi…

【Linux】多线程协同

目录 生产消费模型 BlockQueue阻塞队列模型 BlockQueue.hp Task.hpp mypc.cc RingQueue循环队列模型 POSIX信号量 RingQueue.hpp Task.hpp main.cc 生产消费模型 生产者与生产者之间关系:互斥(竞争) 消费者与消费者之间关系&…

数据库面试题总结自用

MySQL: MySQL的索引原理和数据结构能介绍下吗?B树和B树的区别是什么?MySQL聚簇索引和非聚簇索引的区别?使用MySQL索引都有什么原则?不同的存储引擎是如何进行实际存储的?MySQL的组合索引的结构是什么样的&…

linux环境下启动jar

java -jar XXX.jar & 命令结尾没有 “&” ,则变成 “java -jar XXX.jar ” ,表示在当前ssh窗口,可按CTRL C打断程序运行,或者直接关闭窗口,则程序直接退出 命令结尾添加 “&” ,则变成 “java…

第五章_Redis事务

是什么 官网 能做什么 一个队列中,一次性、顺序性、排他性的执行一系列命令 Redis事务 VS 数据库事务 1 单独的隔离操作Redis的事务仅仅是保证事务里的操作会被连续独占的执行,redis命令执行是单线程架构,在执行完事务内所有指令前是不可能…

WPF样式和触发器的使用

WPF样式是一种用于定义控件外观和行为的强大工具。它可以让开发人员轻松地创建一个可重复使用的控件模板&#xff0c;并应用于多个控件。本文将详细介绍WPF样式的定义、应用、继承以及动态样式&#xff0c;并提供详细的使用实例。 定义样式 在WPF中&#xff0c;样式是通过<…

Android 11.0 添加关机铃声功能实现

1.前言 在11.0的系统rom定制化开发中,在原生系统中,关于开机铃声和关机铃声是默认不支持的,系统默认支持开机动画和关机动画等功能,所以关于增加开机铃声和关机 铃声的相关功能,需要自己增加相关的关机铃声功能 2.添加关机铃声功能实现的核心类 frameworks\base\cmds\bo…