首页 > 其他分享 >TCP 滑动窗口

TCP 滑动窗口

时间:2023-07-28 10:31:36浏览次数:24  
标签:窗口 字节 接收端 TCP 发送 滑动 数据

窗口

由来

TCP 滑动窗口_接收端

按数据包进行确认应答,这样的传输方式有一个缺点:数据包的往返时间越长,通信的效率就越低。为解决这个问题,TCP 引入了窗口这个概念。

有了窗口,就可以指定窗口大小,窗口大小就是指无需等待确认应答,而可以继续发送数据的最大值

主要目的

  1. 保证可靠、有序的数据传递,
  2. 强制发送方和接收方之间进行流量控制。


TCP 滑动窗口_数据_02


滑动窗口简介

发送端

TCP 滑动窗口_TCP_03

TCP 滑动窗口_接收端_04

发送端包的处理的4个部分

  1. 发送了并且确认的包
  2. 发送了但尚未确认的包
  3. 没有发送,但是等待发送的包
  4. 没有发送,并且暂时还不会发送的包

其中 2 和 3 加起来即是接收端计算出的TCP有效窗口(EffectiveWindow)大小

EffectiveWindow=AdvertisedWindow−(LastByteSent−LastByteAcked)

发送缓冲区维护的三个指针

  • LastByteAcked:指针之前为发送已确认
  • LastByteSent:和LastByteAcked之间为发送未确认
  • LastByteWritten:和LastByteSent之间为没有发送,并且在等待发送得

LastByteSent+LastByteWritten=对端advertisedwindow

接收端

TCP 滑动窗口_数据_05

接收端缓冲区维护一组指针(序列号):

  • LastByteRead:指针之后是已经收到的,但是还未被读取应用层读取的
  • NextByteExpected:下一个希望收到的字节
  • LastByteRcvd

如果数据是按顺序到达的,则NextByteExpected指向LastByteRcvd之后的字节,

如果数据是乱序到达的,则NextByteExpected指向数据中第一个缺口的开始

流量控制

起因:发送端和接收端都有一定大小的缓冲区,所以接收端需要一些方法来减慢发送端速度

前提:LastByteRcvd−LastByteRead≤RcvBufferSize(为了避免缓冲区溢出)

计算窗口

接收端公告窗口大小(表示缓冲区中剩余可用空间量):

AdvertisedWindow=RcvBufferSize−((NextByteExpected−1)−LastByteRead)

工作示意图:

TCP 滑动窗口_数据_06

工作机制

  • 当数据到达时,只要前面所有字节也已经到达,接收方就会认可。
  • LastByteRcvd向右移动(递增),这意味着通告窗口可能会缩小,不过是否收缩取决于本地应用程序进程消费数据的速度。
  • 本地进程读取数据的速度和到达数据的速度一样快(导致LastByteRead以与LastByteRcvd相同的速度递增),那么通告窗口将保持打开状态(即AdvertisedWindow = RcvBufferSize)。
  • 接收进程落后了(可能因为对读取的每个字节的数据执行非常昂贵的操作),那么通告窗口将随着每一个到达的分片而变小,直到最终变为 0
  • 接收缓冲区被填满,通告窗口为 0 意味着发送方不能传输任何数据,即使之前发送的数据已经被成功确认。
  • 不能传输任何数据意味着发送缓冲区被填满,这最终会导致 TCP 阻塞发送进程
  • 接收进程再次开始读取数据,接收端 TCP 就能够打开窗口,允许发送端 TCP 传输缓冲区数据。
  • 当这些数据最终被确认后,LastByteAcked增加,缓冲区空间变得空闲,发送过程被解除阻塞并允许继续发送。

知识补充

发送端如何知道通告窗口不再是 0?

TCP 总是发送一个分片响应接收到的数据,并且这个响应包含了Acknowledge和AdvertisedWindow字段的最新值

目前窗口初始化是多少?

原先最大的值为 65525(64K),不过现在内核基本都支持 scaling factor,所以这个大小也就提高到了 1G 字节。其初始值为 20 个 MSS 大小,即 29200 字节。

##cat /proc/sys/net/ipv4/tcp_window_sacling

TCP 滑动窗口_数据_07

TCP 滑动窗口_TCP_08

如何确认窗口何时打开?

当另一方通告窗口大小为 0 时,发送方坚持每隔一段时间发送 1 字节的数据。这个数据可能不会被接受,但还是会尝试,因为每个 1 字节的分片都会触发包含当前通告窗口的响应,最终该响应携带了非零值。这些 1 字节的消息被称为零窗口探测(Zero Window Probes) ,实际上每 5 到 60 秒会发送一次。

发送窗口和MSS

发送窗口决定了能发送多少字节,而MSS决定了这些字节要分为多少个包完成


标签:窗口,字节,接收端,TCP,发送,滑动,数据
From: https://blog.51cto.com/u_5105856/6879155

相关文章

  • 基于PyQt5实现聊天窗口
    本文仅为示例,用于参考,功能并不完整主要实现以下功能:1.重写PlainTextEdit组件实现类似微信ctrl+enter换行,enter发送信息操作2.带头像的消息气泡创建3.消息气泡的自适应大小窗口布局(详细可以通过示例代码中的.ui进行查看)代码获取地址GitHub:PyQt5-Chat-Demo百度网盘:http......
  • WPF 在ScrollViewer控件内部的Slider控件无法触摸滑动
    WPF中在ScrollViewer控件内部的Slider控件无法触摸滑动,是由于ScrollViewer控件默认设置了IsManipulationEnabled为True。<ScrollViewerx:Name="ScrollViewer1"><Slider></Slider></ScrollViewer>WPFScrollViewer的IsManipulationE......
  • 《Win32篇》纯C和Win32实现窗口
    纯C和Win32实现窗口参考链接:https://www.cnblogs.com/zjutzz/p/10806955.htmlwindows下实现窗口显示,如果限定是C/C++语言,并且是原生Windows支持,需要使用GDI或GDI+。一般是在VisualStudio里新建Win32应用程序,而不是Win32consoleapplication(控制台程序),然后使用GDI的一些API,例如......
  • linux查询tcp连接数并排序
    查询已连接[root@rabbitmq-1rabbitmq]#netstat-an|awk'{print$5}'|cut-d:-f1|sort|uniq-c|sort-rn3393172.16.229.2532995172.16.47.212400172.16.229.232186172.16.229.254149172.16.229.240102172.16.229.218这个......
  • 2、了解Webots的窗口-2
    一、WebotsGUI由四部分组成:1、3D窗口:显示并允许与3D模拟交互的窗口;2、Scenetree:它是当前世界的层次表示;3、Texteditor:允许编辑源码;4、Console:显示编译和控制输出;二、分别介绍一下八个菜单栏1、File:允许执行通常的文件操作,如加载,保存等等2、View:允许控制仿真窗口中的可视......
  • TCP基础知识
    TCP详解TCP和UDPTCP和UDP都是传输层的协议。UDP:用户数据报协议,面向无连接,可以单播、多播、广播,面向数据报,不可靠交付TCP:传输控制协议,面向连接的,可靠的,基于字节流,仅支持单播传输TCP三次握手TCP是一种面向连接的单播协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓“连接......
  • TCP和UDP的区别以及各自的应用场景
    TCP和UDP区别:1.连接TCP是面向连接的传输层协议,传输数据前先要建立连接。UDP是不需要连接的,即刻就可以传输数据。2.服务对象TCP是一对一的两点服务,也就是说一条连接只有两个端点。UDP支持一对一,一对多,多对多的交互通信。3.可靠性TCP是要保证可靠交付数据的,数据无差错,不丢失......
  • TCP | UDP
    TCP三次握手第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(SynchronizeSequenceNumbers)。第二次握手:服务器收到syn包并确认客户的SYN(ack=j+1),同时也发送一个自己的SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;第三......
  • 前端Vue仿支付宝自定义可滑动轮播分页宫格菜单组件,可支持九宫格 十二宫格 十五宫格
    背景介绍随着技术的不断发展,传统的开发方式使得系统的复杂度越来越高。在传统开发过程中,一个小小的改动或者一个小功能的增加可能会导致整体逻辑的修改,造成牵一发而动全身的情况。为了解决这个问题,我们采用了组件化的开发模式。通过组件化开发,可以有效地实现单独开发,单独维护,而且......
  • python如何打开命令行窗口
    在Python中,我们可以使用os模块来打开命令行窗口。os模块提供了与操作系统相关的功能,包括运行命令行命令和打开命令行窗口。首先,我们需要导入os模块:importos然后,我们可以使用os.system()函数来运行命令行命令。为了打开命令行窗口,我们可以使用操作系统提供的命令来启动命令行终......