『 Linux 』网络传输层 - TCP(二)

文章目录

    • TCP六个标志位
    • TCP的连接
      • 三次握手
    • 四次挥手
      • 为什么是三次握手和四次挥手
    • 重传机制

TCP六个标志位

在TCP协议报文的报头中存在一个用于标志TCP报文类型的标志位(不考虑保留标志位),这些标志位以比特位选项的方式存在,即对应标志位为0则表示为假,对应标志位为1则为真;

  • SYN

    用于建立连接,连接发起方发送SYN请求,表示希望发起一个连接,同步序列号;

  • ACK

    标识确认,该位被设置时,确认号字段有效,用于确认接收到的数据;

  • FIN

    用于关闭连接,一方发送FIN表示它已经完成数据发送并希望关闭连接;

  • RST

    用于重置连接,表示当前连接有问题,需要强制断开,通常用于错误或异常情况;

    RST报文被接收后需要重新进行三次握手来建立一个新的连接;

  • PSH

    推送数据,提示接收方应用程序应立即读取数据而不是在缓存中等待更多数据;

    本质上TCP也是一种生产者消费者模型的体现,其中发送方的用户层与接收方上层的用户层各担任了生产者和消费者的身份,其中发送方的用户层作为生产者,接收方的用户层作为消费者,当接收缓冲区满了后发送方再向接收方发出的数据流将被丢弃,在对于流量控制而言本质上就是在网络中的一种同步应用;

    PSH报文可以通过告诉接收方应尽快将这些数据流传给应用层避免数据长时间积累在接收缓冲区中导致接收方的接收缓冲区被写满;

  • URG

    表示紧急数据,紧急指针字段有效,用于标示紧急数据的位置,提示接收方优先处理;

    在操作系统中存在一个专门用于处理紧急数据的空间,当紧急数据被发送过后且URG标志位被设置,表示紧急指针有效,对应的紧急数据将会优先被处理;

    对于TCP而言,其数据流是按序到达的,所以为了不导致大面积的数据乱序,紧急指针所指向的紧急数据很小,通常只有一个字节;

    大部分情况下紧急数据用来处理或者检查对端接收缓冲区中数据长时间不被处理导致的发送方所发送的数据无法被接收方接收导致发送方未接收到应答等情况;

    可以将URG标志位理解为一个优先通道;

    可以通过系统调用接口send()设置对应的MSG_OOB选项来设置紧急数据,对应的也可通过系统调用接口recv()同样设置MSG_OOB选项来读取对应的紧急数据;

六个标志位中每一个标志位都标示着该TCP报文的类型,即一个TCP报文可能是多种类型,如在进行三次握手时,被握手方需要返回一个SYN+ACK的报文,其中该报文中的SYN表示也需要向对方建立起连接,而ACK表示的是对对方发起的SYN报文进行应答;

同时为了保证安全性,操作系统通常不会直接让用户直接修改对应的标志位,但对应的操作系统会为用户提供一些系统调用接口来间接修改报文的属性类型;

如当用户调用connect()系统调用接口向一个服务端发起连接时,本质上是让系统构建一个SYN类型的TCP报文并发送给对端;

对应的当一个已经连接的服务端或是客户端调用close()时本质上也是让系统在底层构建一个FIN类型的报文,并发送给对方表示希望断开该次连接;


TCP的连接

TCP是一个保证可靠传输的网络协议,其为了保证数据传输的可靠性,通常要与服务端建立起连接,但尽管TCP协议制定了若干的约定来保证数据在传输中的可靠性但也避免不了一些不可抗拒的因素;

本质上TCP协议保证可靠传输的前提是在与对端建立连接的前提下,保证未发生不可抗力异常时数据的传输(不可抗力异常通常为断电或设备故障,物理连接中断或是网络设备配置错误,任何一端应用层的崩溃等情况);

通常情况下服务器都是一对多的,即一台服务器将对应存在若干个客户端,当一台客户端向服务器发起连接请求时服务器中可能也在处理来自其他客户端的连接请求或是维护与其他客户端的连接,维护的方式同样的采用的是 “先描述后组织” ,无论是服务端还是客户端为保证连接的可靠性系统层面都要对已经建立好的连接创建一个对应的结构体,通过实例化结构体对象再以特定的数据结构将多个该结构体对象组织在一起,如链表;

对应的任何一端对连接的维护都是具有成本的,即需要花费时间和空间;

  • TCP允许连接建立失败

TCP所保证的可靠性是建立在已经建立连接的基础上,但实际上在建立连接时可能会因为多种因素导致连接建立失败,TCP能保证数据传输可靠但是无法保证在建立连接时能完全避免连接建立失败的情况;


三次握手

TCP协议建立连接时需要先进行三次握手;

所谓三次握手即为,请求建立连接方向对端发送SYN报文表示希望与该端建立连接,对端进行应答并告知也希望与该端建立连接返回一个SYN+ACK报文,请求方向对端返回ACK报文表示接收到对端的请求;

以该图为例:

  • Client向Server发送SYN报文
  • Server向Client返回SYN+ACK报文
  • Client向Server发送ACK报文

其中图中的每次报文发送的斜线表示每次报文的发送与接收具有时间差;

以客户端的视角而言,当客户端发送第三次握手的ACK报文后则表示该次握手已经建立成功,将会创建一个对应的结构体用于管理该连接;

而对于服务端而言,当其接收到第三次握手的ACK报文才表示该次连接真正被建立成功,才会生成对应的结构体对象来管理该连接,当服务端接收到三次握手中的最后一个ACK报文后不会再对该ACK报文进行应答,这也是 “应答不会再被进行应答” ;

即通常情况下对于客户端而言,当其认为连接已经建立成功后将会正常与服务端进行正常通信,若是服务端未接收到最后一个ACK报文就接收到了客户端的正常通行报文(数据流),服务端将会认为该连接并未建立成功,并不会接收该报文,而是向客户端发回一个RST报文告诉该连接并未建立成功,要求客户端重新发出最后一个ACK报文以要求建立连接;

这里也涉及到确认序号的问题,当发送端发出一个TCP报文给接收端,对应的接收端将对该报文向对端返回一个ACK报文表示应答,其中返回的ACK报文中的确认序号通常为 所接受报文序号+有效载荷大小 ,通常SYN标志位和FIN标志位将会占用一个序列号,所以对应的当服务器端接收到一个SYN报文时,假设该报文序列号大小为x,则服务端需要返回一个序列号大小为x+1SYN+ACK报文,示例为如下:

  • 第一次握手

    客户端发送一个SYN报文,假设序列号为x;

    Client -> Server : SYN, SEQ = x
    
  • 第二次握手

    服务器收到SYN报文,返回SYN+ACK报文,假设服务器的初始序列号为y;

    Server -> Client : SYN+ACK, SEQ = y, ACK = x+1
    
  • 第三次握手

    客户端收到SYN+ACK报文,返回ACK报文;

    Client -> Server: ACK, SEQ = x+1, ACK = y+1
    

当应用层想要该端与一个服务器端建立起连接,需要调用connect()系统调用接口使底层构建一个SYN报文,但实际上connect()只负责要求系统构建报文,其函数本身并不参与握手(只发起握手,不关心握手细节);

当一个执行流调用connect()系统调用接口使系统构建SYN报文后将进行阻塞,直到握手完成,当以客户端的视角第三次握手被发出后对应的连接将视为成功,对应的系统将为该连接维护对应的结构体,并且将该连接以套接字描述符的方式返回给connect()函数表示连接建立完成;

对应的当一个服务端需要获取一个来自客户端的连接时同样要调用accept()系统调用接口,同样的该接口不参与握手细节,当一个执行流调用该系统调用接口时对应的该执行流也会进入阻塞状态,直到三次握手完成并且连接被建立成功,对应的该被维护起来的连接将以套接字描述符的方式交给该函数作为返回值;


四次挥手

四次挥手是正常情况下连接断开的过程,通常为申请断开连接方调用系统调用接口close()让系统构建一个FIN报文并发送给对方;

四次挥手的过程为:

  • 第一次挥手

    发送方向接收方发送一个FIN报文表示希望与对端断开连接;

  • 第二次挥手

    接收方向发送方返回一个ACK报文表示接收到这个断开连接请求;

  • 第三次挥手

    接收方向发送方发送一个FIN报文表示希望与对端断开连接;

  • 第四次挥手

    发送方向接收方返回一个ACK报文表示也收到了这个断开连接请求,至此连接彻底断开;


为什么是三次握手和四次挥手

  • 为什么是三次握手

    三次握手是TCP为了保证双方通信时具有可靠性所定制的一种策略;

    而三次握手可以确保客户端和服务端至少都向对方发送了一次消息,从而确保连接建立的更为可靠;

    以朴素的角度来看三次握手实际上也可以被解析成四次握手;

    但为了提升连接创建的效率,TCP采用捎带应答的策略,在第二次握手中将ACK报文与SYN报文整合成了一个报文,即为SYN+ACK报文;

    在三次握手中能够确保双端都对对方进行一次消息的发送以及消息的接收来确保连接的稳定,因此三次握手中任何一次握手都不能少;

    假设三次握手的数量减少,连接的可靠性将大大降低,如以下几种情况:

    • 单次握手

      单次握手时通常为当客户端向服务端发起一个连接请求后服务端无法保证连接的可靠性就直接建立起对应的连接并进行维护,既不能保证客户端向服务端方向的数据传输是否可靠(服务端不进行应答即建立连接,不能保证服务端是否接收到对应的连接请求),也无法保证服务端向客户端方向数据传输是否可靠;

      同时维护连接通常是具有成本的,单次握手可能会导致同一个客户端向一个服务端大量发送连接请求,只要服务端一接收就建立起对应的连接并且对这些连接进行维护,将会大大占用服务端资源;

      一次握手服务端无法确认客户端的状态,无法保证连接的有效性和安全性;

    • 二次握手

      二次握手对于客户端而言,仍无法保证服务器已经准备好通信,二次握手通常意味着客户端发送SYN报文,服务端返回SYN+ACK报文,在未接收到客户端的ACK前服务器就已经认为连接已经成立,但实际上客户端收到SYN+ACK后可能由于种种原因无法进行数据传输,如网络中断等;

      而服务端将会为一个可能无效的连接预留资源,同样会面临无法确认客户端是否通信就绪的问题;

    三次握手将建立一个稳定可靠且能够确保全双工的通信连接,即任意一方都可以有效的进行发送数据和接收数据;

    通常情况下,客户端与服务端的关系通常是一对多的,即一个服务端对应着若干个客户端,而一次握手和二次握手两种方案最终都把负载交到了服务端身上,服务端随时都维护着一些无用资源,即并不进行通信了连接进行维护;

    三次握手可以将负担均匀的双方分配而不是只有单单服务端具有负担;

    同时一次握手和二次握手的方案将大大提升服务端受到SYN Flood(通过发送大量伪造的SYN报文,迫使服务器分配大量资源维护无效连接从而使其无法处理正常请求)等DoS攻击;

    同时三次握手不仅确保了连接的可靠性,三次握手时双方所发的报文也是一种协商报文,协商的包括双方的起始序号,确认序号位置,窗口大小等等;

    同时当任意一端发送RST报文后,表明当前连接被强行中断,任何已建立的连接状态信息都会被销毁,如果需要重新建立通信必须进行新的三次握手,以建立一个全新的TCP连接;

  • 为什么是四次挥手

    三次握手是建立通信连接的过程,而四次挥手是断开连接的过程,断开连接与建立连接是不同的,在连接建立过后数据是双向发送的,客户端和服务端任意一方都既扮演着发送方,也扮演者接收方的角色;

    当一端将数据发送完后准备关闭连接其无法确保对端是否还有数据未发完,所以断开连接的操作通常为四次挥手,即双方在确保没有数据要发送给对方时都要向对方发送连接关闭的请求;

    假设客户端主动向服务端发起断开连接的请求(客户端断开连接请求前的所有数据段已经发送完成),即客户端调用系统调用接close()时系统将生成一个FIN报文发送给对方并进入一个FIN_WAIT_1的状态,即第一次挥手;

    当服务端接收到FIN报文后将无条件进行ACK报文答复,即第二次挥手;

    此时连接并没有断开,只是客户端不再向服务端发送数据,对应的客户端将进入一个FIN_WAIT_2的状态,对应服务端也将进入一个CLOSE_WAIT的状态,这里客户端不发送数据表示不主动发送数据,对于数据的应答客户端还是会照常进行;

    在连接完全断开前也要保证数据传输的可靠,即当客户端一样可以接受来自服务端的数据并且处理对应数据;

    当服务端发送最后一条数据后服务端将主动向客户端发送一个FIN报文,即第三次握手;

    同时服务端能够确认自己没有数据需要再发送给客户端也能确认客户端没有数据再发送给本端,但是其无法保证客户端的数据已经全部处理完毕或是无法保证数据没有丢包,所以连接还是不能断开;

    若是数据段在网络中丢失或是出现其他情况时服务端需要启用重传策略;

    当客户端接收完并处理完所有数据段后将对服务端再次发送一个ACK报文表示确认服务端的连接断开请求;

    至此连接彻底关闭;


重传机制

为了保证数据传输时的可靠性,TCP定制了一系列的重传机制以避免数据丢失,常见的重传机制有快速重传,超时重传,选择性重传和快速恢复;

  • 快速重传

    快速重传用于发送方识别到所发数据丢失从而快速对数据进行重发;

    通常情况下快速重传机制将在接收方返回三个重复的ACK报文时被触发;

    假设发送方向接收方发送三个报文,对应报文的序列号为499,999,1499,将在下面情况发生快速重传;

    • 发送方发送三个报文段

      报文段1 : 序号499

      报文段2 : 序号999

      报文段3 : 序号1499

    • 接收方行为

      接收方接收到序号499报文,返回ACK报文,序号为500;

      接收方未接收到序号999报文,继续等待;

      接收方接收到序号1499报文,因为期望先收到序号999报文,因此发送重复序号为500ACK报文;

    • 发送方行为

      发送方收到第一个序号为500ACK报文,忽略;

      发送方收到第二个重复序号为500ACK报文,怀疑记录丢失,记录第二个重复ACK报文;

      发送方收到第三个序号为500ACK报文,触发重传机制;

    • 触发快速重传

      发送方立即重传丢失的报文段(序号为999);

  • 超时重传

    超时重传是TCP最基本的一种重传机制,通过定时器的方式来决定何时需要重传数据;

    其工作原理为:

    • 发送数据并启动定时器

      发送方再发送一个数据段后会启动一个定时器并记录下此数据段的序列号;

      定时器设置的超时时间通常是由 往返时间 和网络状态估算来的;

    • 等待确认

      发送方等待接收方响应回的ACK报文来确认已经成功接收到该段数据段;

      如果在定时器超时之前收到对应数据段的ACK报文则停止定时器并继续发送后续数据段;

    • 定时器超时并重传

      如果定时器到期时仍未收到对应报文的ACK应答,发送方将在新的定时器周期内重新发送该未经确认的数据段;

      超时时间一般采用 指数回退算法 来避免频繁重传所引起的网络拥塞;

  • 快速恢复

    快速回复机制通常与快速重传机制结合使用,当检测到丢失的数据段时,通过调整拥塞窗口以避免传输速率下降过多;

    • 快速重传后的拥塞控制

      当接收到三个重复的ACK报文并且执行了快速重传后,发送方将窗口大小减半并设置慢启动门限;

      具体来说 : ssthresh = cwnd/2 , 然后 cwnd = ssthresh + 3 * MSS;

    • 继续发送数据

      在快速恢复期间,发送方按照新的cwnd继续发送数据段而不进入漫长的慢启动过程;

      发送新的数据段是为了利用窗口中未消费的部分确保不浪费带宽;

    • 恢复正常传输

      当收到新的ACK报文后,将会把cwnd调整到适当的大小并恢复正常传输;

  • 选择性确认

    选择性确认也被称为SACK;

    可以告知发送方具体那些数据段已经被接收和丢失,前提是通信支持SACK机制;

    假设发送方发送三个报文段,序号分别为200,400(丢失),600;

    • 接收方发送SACK

      接收方接收到序号200的报文段,发送ACK201并附带SACK选项标记接受情况;

      接收方接收到序号600,发送ACK201并在SACK中标记已接收区间以及遗漏部分400-599;

    • 发送方根据SACK重传

      发送方根据SACK选项确认丢失的报文段(序号400-599)并仅重传这部分数据;

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

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

相关文章

LeetCode --- 421周赛

题目列表 3334. 数组的最大因子得分 3335. 字符串转换后的长度 I 3336. 最大公约数相等的子序列数量 3337. 字符串转换后的长度 II 一、数组的最大因子得分 数据范围足够小,可以用暴力枚举移除的数字,得到答案,时间复杂度为O(n^2)&#…

动态规划-回文串问题——5.最长回文子串

1.题目解析 题目来源:5.最长回文子串——力扣 测试用例 2.算法原理 1.状态表示 判断回文子串需要知道该回文子串的首尾下标,所以需要一个二维数组且数据类型为bool类型来存储每个子字符串是否为回文子串, 即dp[i][j]:以第i个位置为起始&a…

微积分复习笔记 Calculus Volume 1 - 4.4 The Mean Value Theorem

4.4 The Mean Value Theorem - Calculus Volume 1 | OpenStax

docker engine stopped

1)环境:win 10 2)docker安装时已经已经安装了虚拟机 3)启用网络适配器 4)启用docker服务(依赖服务LanmanServer) 5)全都弄好了,docker还是打不开,没办法了&a…

【VM实战】VMware迁移到VirtualBox

VMware 虚拟机开机卸载VMware Tools 调整虚拟磁盘 对于Windows 10及以上的虚拟机,一般VMware默认都会选Nvme固态硬盘。在导出前必须将其改为SATA,否则VirtualBox导入会报Appliance Import错误 (E_INVALIDARG 0x80070057) 先删掉当前盘的挂载&#xff…

某本书上的一张序列图评点

贝贝 2019-8-24 10:56 潘老师,这个图是不是不太对。插卡,输入密码并不是ATM的职责? UMLChina潘加宇: 这种图用建模思维一挤压,脓包太多了。 问题一、几个生命线上的实例,抽象级别不一致。 ATM用户--系统&#xff0…

Docker | 校园网上docker pull或者docker run失败的一种解决方法

场景 需要从仓库拉取镜像 无论使用命令docker pull 还是 docker run 但是总是显示如下的错误: 解决方法 查看虚拟机网络连接方式 Linux上检查校园网是否登录 有界面 无界面 只是命令行操作的Linux 关于Linux服务器端更新命令apt update没有效果问题总结(校园网认证)

推荐一款功能强大的AI实时变声器:FliFlik Voice Changer

FliFlik VoiCE Changer是一款专注于声音变换与音频处理的创新软件,旨在满足从日常娱乐、游戏直播到播客制作、专业音频编辑的多种应用场景需求。无论是想在游戏中变换声音逗乐队友,还是在播客中塑造个性化的音效,这款软件都能提供灵活而强大的…

YOLOv8改进,YOLOv8改进损失函数采用SlideLoss来处理样本不平衡问题,助力涨点

摘要 作者提出了一种基于 YOLOv5 改进的实时人脸检测模型,称为YOLO-FaceV2。设计了一个感受野增强模块(RFE)来提升小尺度人脸的感受野,并引入了 NWD 损失,以弥补 IoU 在小目标位置偏差上的敏感性。针对人脸遮挡问题,提出了 SEAM 注意力模块,并引入了排斥损失进行优化。…

【django】django RESTFramework前后端分离框架快速入门

目录 一、搭建项目开发环境 1.1 pycharm创建项目 1.2 修改配置settings.py 1.3 新增 static与staticfiles文件夹 1.4 生成数据表 1.5 创建超级用户 1.6 启动项目 二、安装REST_Framework 2.1 安装 2.2 配置settings 2.3 重新执行生成数据库脚本 三、修改路由 四、s…

【微服务】Java 对接飞书多维表格使用详解

目录 一、前言 二、前置操作 2.1 开通企业飞书账户 2.2 确保账户具备多维表操作权限 2.3 创建一张测试用的多维表 2.4 获取飞书开放平台文档 2.5 获取Java SDK 三、应用App相关操作 3.1 创建应用过程 3.2 应用发布过程 3.3 应用添加操作权限 四、多维表应用授权操作…

二维legendre多项式

Legendre 多项式常用来表征方形波前的畸变。 目录 一维legendre多项式正交性自正交性 二维Legendre多项式正交性证明 可视化二维 Legendre 多项式解释 Legendre拟合方法1MATLAB 实现解释方法21. 定义一维 Legendre 多项式函数2. 生成二维 Legendre 多项式矩阵3. 计算 Legendre…

台式电脑如何改ip地址:全面解析与实操指南

有时候,由于IP地址冲突、网络安全、隐私保护或特定应用需求,我们可能需要更改台式电脑的IP地址。然而,对于不熟悉网络设置的用户来说,这一过程可能显得复杂而陌生。本文将通过全面解析与实操指南,帮助大家轻松掌握台式…

【私聊记录】最近在忙什么啊?听说你在学人工智能?

小舒:哎,你最近在忙什么啊? 小元:我在学习人工智能呢。 小舒:人工智能?难不难学啊? 小元:不难,找到正确的学习姿势就不难了! 小舒:那你为什么想学…

电动越野车行业全面深入分析

电动越野摩托车是将电动技术与越野性能相结合的一类摩托车,采用电力驱动,具有环保、节能、低噪音等优点,同时保留了越野摩托车的强劲动力和适应复杂地形的能力。电动越野摩托车通常配备高性能电动机和电池组,可提供强劲的动力输出…

ctfshow--xss靶场web327-web333(一命速通不了的靶场)

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 web327 打开页面是一个写信页面。 这里题目暗示不明显。 这里是要给admin写信&#xff0c;让他触发我们的xss。(不看解析不知道有个admin用户) payload: <svg οnlοadwindow.location.hrefhttp://xss平台地址…

法律文件智能识别:免费OCR平台优化数字化管理

一、系统概述 在法律行业&#xff0c;纸质文件的数字化需求日益迫切&#xff0c;合同、判决书、协议等文件的管理成为法律部门的一大难题。传统手动输入不仅耗时&#xff0c;且易出错。思通数科的OCR识别平台应运而生&#xff0c;以其开源、免费的特性为法律文档管理提供了智能…

Flutter-Engine 的定制实践:Text 绘制流程浅析及自定义underline的间距

前言 最近工作中处理的文本相关的内容较多&#xff0c;不论是刁钻的需求还是复杂的问题&#xff0c;最终都会引向一点“Flutter中的文本是如何绘制的&#xff1f;”。 这里我将以“调整下划线与文字的间距”为切入点并结合自定义Engine&#xff0c;记录一下我的个人分析和实践…

“基金申请精要:国自然基金撰写与SCI发表“

国自然基金项目撰写技巧与ChatGPT融合应用 随着社会经济发展和科技进步&#xff0c;基金项目对创新性的要求越来越高。国家级和省级等各类项目的申请层出不穷&#xff0c;项目书的撰写几乎占据了申请人的全年时间。申请人既需要提出独特且有前瞻性的研究问题&#xff0c;具备突…

java的依赖注入

java的依赖注入是个什么东西&#xff1f; 计算机专业相关知识2024-08-07 17:26河北 摘要 •帮你速读文章内容 java中的依赖注入&#xff08;Dependency Injection, DI&#xff09;是一种软件设计模式&#xff0c;用于减少代码间的耦合度。它允许一个对象&#xff08;被依赖的…