当前位置: 首页 > article >正文

linux网络 | TCP报头之六个标记位与部分可靠性策略

        前言:本节内容讲述TCP报头里面的六个标记位以及一些保证TCP可靠性的方案(连接管理设计状态的分析滑动窗口占用篇幅大,放在下一节讲解)。 TCP可靠性方案也是学习TCP的一个重要的板块。 本节就来讲述一些可靠性方案。 下面废话不多说,开始我们的学习吧!

        ps:本节内容需要一些前面学习的穿插内容, 友友们最好看一下这篇文章再来学习比较好哦:linux网络 | 传输层TCP | 认识tcp报头字段与分离-CSDN博客

目录

为什么要有六个标记位

六个标记位解析

ACK、SYN、FIN        

 PSH

RST 

URG 

可靠性策略

检验和 

序列号 

确认应答

超时重传


为什么要有六个标记位

         服务器和客户端 1: n进行tcp通信的时候,一定要先建立连接,三次握手。然后结束通信,tcp也要断开连接四次挥手。在建立和断开之间,还要进行正常的数据通信,tcp在建立连接的时候一定要发送tcp的报文。 断开连接也要, 正常通信也好,都要发送tcp报文(至少要有报头, 可以没有数据)。所以,通信之前,有些tcp请求是用来建立链接的,有些是用来正常通信的,有些是用来断开连接的。 这就注定了tcp收到的报文, 本身是有类型的。
        这个类型,接收方怎么知道报头的类型是什么呢? 所以就有了六个标记位 (区分tcp报文的类型)。

六个标记位解析

ACK、SYN、FIN        

        关于ACK,SYN,FIN很简单。 这三个是在三次握手和四次挥手的时候要使用的标记位。 具体就是:

  • ACK确认号是否有效,即确认应答
  • SYN请求建立链接;我们把携带SYN标识的称为同步报文段,即请求握手。
  • FIN: 通知对方,本端要关闭了 

 PSH

        PSH是提示接收端应用程序立刻从TCP缓冲区把数据读走

        什么意思, 就是说如果我们的发送方向对方发送数据,发送了大量的数据,导致对方的接收缓冲区已经满了。这个时候,会发生什么呢?

        是不是就是不能再像对方的接收缓冲区发送数据,然后发送方就堵塞了!!! 但是,发送方堵塞不能一直堵塞,所以如果接受方的上层一直不处理接收缓冲区的报文,那么发送方就可以发送一个PSH报文。表示催促对方赶紧处理报文腾出位置! 即表示提示对方应该立刻把TCP缓冲区里面的报文读走。

RST 

         RST对方要求重新建立连接,我们把携带RST标识的称为复位报文段 

         我们说TCP是保证可靠性的。那么是否建立连接,必须得成功呢?——tcp虽然保证可靠性,但是tcp允许链接建立失败。

        我们要知道的另一个点是,一个客户端在服务端求接,这个时侯我们的服务定同时存在多个已经建立好的链接,这么务摊接,服务要对这么多接进行管理,关闭,所以服务端就要对这些链接进行管理。

        所以,我们如何理解”链接”概念呢?

        客户端和服务器双方建立好连接的本质,就是双方的操作系统内为链接创建struct结构体。这个链接结构体里面包含链接相关的属性,比如说链接什么时候建立、客户端的端口号等等。

        我们也可以把链接结构体之间用指针相连,然后我们对连接的管理,就转化成了对链表的增删查改。

        CS维护链接也是有成本的。这里的这个成本就是上面创建结构体,要花时间,要花空间。
        在我们大量客户端进行连接时,就可能出现链接出现异常的情况。就比如客户端认为链接建立好了,但是服务器认为链接没有建立好, 这个时候客户端创建了结构体, 服务端没有创建, 这个成本就花在了客户端这边。 (后面我们会谈一下这个成本问题)

        我们上面说CS是有成本的, 首先我们先不谈成本的解决方法, 先看一下为什么会有成本,我们用三次握手来细讲:

        这些请求的线之所以不直直的画,就是因为从请求发送到拿到请求之间是有时间差的。


        上面的三次握手中有一个小问题,就是在客户端最后一次ACK的时候,是在客户端发出ACK后就认为建立连接成功了呢,还是要知道服务器已经收到ACK后客户端才会认为连接已经建立好呢?

        这里的答案是,只要发出去,就认为连接成功,没有应答!!!! 

        所以tcp三次握手, 本质上是在赌, 赌最后的ACK服务端能够收到。但是前两次握手的可靠性是能够保证的,不能保证的只有最后一个ACK。

  •         所以,client在三次握手中,认为只要把三次握手中的第三次报文发出,就认为连接建立好了!!! 
  •         如果ACK丢失了,此时服务端就认为这个连接没有建立好,此时就是客户端和服务端对连接是否建立成功认知不一致。然后客户端这个时候发消息,此时服务端认为连接还没有建立好,就会应答RST标记回去,重新建立连接。重新三次握手。

        综上, RST是客户端和服务器,双方对连接认知不一致,即连接建立异常的情况下重新连接使用的。

URG 

        URG是紧急指针是否有效 

  •         有些情况下,想要让上层高优先级去处理一些数据,此就可以设置一个URG标志位,此URG标记位如果为0,表示无效,16位紧急指针没有意义,填写一个0即可。
  •         但是URG如果为1,表示这个报文内部包含了紧急数据,要求当前要紧急处理,这个16位紧急数据就代表在整个tcp数据当中,紧急数据的偏移量是多少。紧急数据只允许是一个字节。 

       

        什么情况下我们会使用这个紧急数据呢? 

        假如这个服务端很卡,所以客户端就要询问他为什么这么卡。这个时候客户端就要向服务端发起询问,询问服务器是怎么回事, 所以我们就需要服务端支持读取紧急数据 + 软件功能提供状态编号
        假如服务端这个时候很卡,我们发送了多少数据都没有回应。这个时候我们就可以发一个紧急数据,这个紧急数据,在服务端内有专门的位置读取这个紧急数据。然后服务端读取这个紧急数据,读上来之后,因为处理的信息量不大,然后服务端就要把状态返回给客户端(比如1,2,3)这样询问和响应的数据就加快了。 

可靠性策略

检验和 

        十六位检验和, 报头中的字段,和UDP的一样, 都是检验数据在传输过程中有没有出现偏差。

序列号 

        32位序号, 避免了数据包乱序的问题和数据包的重复问题(每一个序号只有一条报文)

确认应答

         保证了确认应答消息之前的消息的可靠性。 值得一提的是, 确认应答, 起始就是ACK,所以就是ACK应答机制。

超时重传

        上一节的超时重传我们有一些细节没有讲到, 这一节我们补充一些:

        为什么要有超时重传,主机A在向主机B发送数据时,如果是数据本身丢失了。即主机B根本就不知道A给他发过数据。所以B也就不会给A进行应答。那么A就收不到B的应答,他就不知道自己刚刚的报文到底有没有被B收到。

        所以为了给丢了做一个定义,就规定了一个特定的时间间隔,凡是超过这个时间间隔的报文,如果没有收到应答,那么就当成丢了。超时之后,当成丢了之后,就要开始重新发送报文, 这个就叫做超时重传机制。

        另外还有一种情况就是主机A给主机B发送消息。主机B收到了消息,发送回去确认应答,但是确认应答丢了,主机A同样收不到应答,超过特定时间间隔后,主机A就要进行超时重传。 

        对于第一种情况,主机A确认丢失后重发就重发了。但是第二种情况下,主机B明明收到了主机A的报主机A还要重新发,就势必会造成主机B收到 重复报文重复报文也是一种不可靠情况,所以就要去重。所以这里又用到了序号。

         序号是如何设置的呢? 

        设定特定时间间隔怎么设置呢。这个我们就要思考一个问题。

        就是如果此时网络速度很快,那么这个时间间隔就不能太长。因为如果时间太长,在网络速度很快的情况下就非常浪费时间。

        如果此时网络速度很慢,那么这个时间间隔就不能太短,因为如果时间太短,在网络速度很慢的情况下,就很容易发送一个报文,这个报文就发生超时,然后重传。这样就容易发送大面积重传的现象。

        所以,我们就可以得到一个结论,超时重传的时间一定是动态的,是随着网络情况发生变化的。 

        操作系统中的解决方案是:Linux中(BSD Unix和Windows也是如此),超时以500ms为一
个单位进行控制,每次判定超时重发的超时,时间都是500ms的整数倍 。

        如果重发一次之后,仍然得不到应答,等待 2*500ms 后再进行重传。如果仍然得不到应答等待 4*500ms 进行重传依次类推, 以指数形式递增,累计到一定的重传次数,TCP认为网络或者对端主机出现异常,强制关闭连接。

  ——————以上就是本节全部内容哦, 如果对友友们有帮助的话可以关注博主, 方便学习更多知识哦!!!   


http://www.kler.cn/a/517325.html

相关文章:

  • 【中间件快速入门】什么是Redis
  • 【Ubuntu】安装SSH启用远程连接
  • 【python】四帧差法实现运动目标检测
  • 2025美赛C题完整代码+建模过程
  • 使用 Confluent Cloud 的 Elasticsearch Connector 部署 Elastic Agent
  • vim如何显示行号
  • 【无标题】mysql python 连接
  • qml Dialog详解
  • 达梦拷贝DM_HOME的复制安装
  • Python Numpy 数组的条件筛选
  • ubuntu 把安装好的 wine软件 打包 到另外一台机器
  • R语言学习笔记之高效数据操作
  • 第17篇:python进阶:详解数据分析与处理
  • SpringCloud之服务间通信超时:突破微服务的“时间枷锁”
  • 如何在Windows系统上安装和配置Node.js及Node版本管理器(nvm)
  • 基于微信阅读网站小程序的设计与实现(LW+源码+讲解)
  • HarmonyOS基于ArkTS卡片服务
  • # AI绘图中的Embedding、CLIP、Flux中的Clip与LCM SDXL加速生成解析
  • Vue 2 + Element UI 实现密码显示、隐藏切换功能
  • rust学习-宏的定义与使用
  • flutter入门系列教程<三>:tabbar的高度自适用,支持无限滚动
  • UDP/TCP ⑤-KCP || QUIC || 应用场景
  • 【2024年华为OD机试】 (C卷,100分)- 考勤信息(JavaScriptJava PythonC/C++)
  • 【leetcode100】二叉树的右视图
  • 职责链模式
  • MES系统和ERP系统有什么区别?