【TCP】核心机制:延时应答、捎带应答和面向字节流

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 【TCP】核心机制:延时应答、捎带应答和面向字节流

延时应答

尽可能降低可靠传输带来的性能影响

提升性能==>让滑动窗口变大

  • 如果我们立即返回 ACK,此时窗口大小就是 4KB
  • 其实在收到数据的时候,应用程序也在源源不断的消费接收缓冲区中的数据
  • 所以我们返回的时间可以晚一些,这样应用程序就有机会读取缓冲区中更多的数据
  • 假设让 ACK 不是立即返回,而是 100ms 之后再进行返回,这就意味着,此时在 100ms 之内,应用程序可能又消费掉 2KB 的数据了,此时返回的 ACK 携带的窗口大小就是 6KB
    延时返回的 ACK 窗口大小,大概率要比立即返回 ACK 的窗口大小更大,因为在这个时间里,会有一个消费数据的过程
  • 不是一定,只是有“大概率”,关键取决于程序是不是在不停地读取数据、延时时间内发送方是否会新发数据过来(发多了窗口还变得更小了)

捎带应答

在延时应答的基础上,引入的提升效率的机制,把返回的业务数据和 ACK 两者合二为一了

实际网络通信中,大部分情况都是“一问一答”的形式

  • ACK 是内核返回的,是收到请求之后,立即就返回 ACK
  • 响应,则是应用程序返回的,代码中根据请求,计算得到响应,再把响应写回到客户端
    正常情况下,ACK 和响应是不同的时机,无法合并。但是,ACK 涉及到“延时应答”,
  • 延时应答就会使 ACK 的返回时间被往后拖,这样一延时,就可能赶上接下来发送响应数据的操作了
  • 也是就可以在发送响应的时候,把刚才ACK的信息也带上
  • 本身 ACK 报文,不需要载荷,包头中,设置 ACK 这一位为 1,设置窗口大小的值,设置确认序号
  • 响应数据主要是设置载荷,和 ACK 不冲突,可以共存
  • 在四次挥手中也说到过这样的情况,ACK 和 FIN 是不同的时机,不能合并在一起
  • 但是,在延时应答之下,ACK 可能返回的时间更晚,此时,就可能可以和 FIN 合并,使四次挥手变成三次挥手

比如说,你在床上口渴了,但是你不想起来,就等到要上厕所的时候再起来,顺带把水喝了

延时应答,捎带应答都是 TCP 提升性能的机制。TCP 之所以复杂,不仅仅在考虑可靠传输,还要在可靠传输的基础上尽可能提高效率

面向字节流

读写 100 个字节的数据

  1. 可以一次读写一个字节,分 100 次
  2. 一次读写 10 个字节,分 10 次
  3. 一次读写 50 个字节,分 2 次
  4. 一次读写 100 个字节,一次搞定

粘包问题

通过面向字节流的方式传输数据,都是会涉及到“粘包问题”

  • 粘的是 TCP 携带的载荷(应用层数据包)
  • aaa、bbb、ccc 分别是三个不同的应用层数据包
  • 接收方那边就有一个接收缓冲区,三个数据就进去了
  • 应用程序需要读取接收缓冲区中的数据,由于 TCP 是面向字节流的,所以怎么读都可以
  • 可以读成:a,aa,b,bb,ccc
  • 也可以:aaa,b,b,bc,cc
  • 存在很多种读法
  • 但只有一是正确的读法,才是完整的“应用层数据包”

应用层在 TCP 的接收缓冲区中连成一片,就称为“粘包问题

要想解决粘包问题,关键就是要明确“包之间的边界

方案一:指定分隔符

前面在写 TCP Echo Server 的时候,我们约定:请求和响应都以 \n 结尾。

  • 发送请求响应的时候,专门使用 println 进行写数据
  • 接受请求响应的时候,专门使用 scanner.next 按照 \n 进行解析

需要确认数据内容的正文中,不能包含分隔符。如果传输的数据,是纯文本数据的话,此时使用 \n 或者 ; 之类的可能都不合适,但是可以使用 ASCII 码表中的一些不常见的字符

方案二:指定数据的长度

比如,约定在每个应用层数据包开头的几个字节,表示数据包的长度

  • 如果是传输二进制数据,这个方案就很有用

如果希望在文件中存储结构化数据,也是存在这样的问题的。所以存文件,也经常会使用 XML/JSON 这样的格式来存储(也就是解决粘包问题)

UDP 这种面向数据报的传输方式,不涉及到上述问题,因为 send/receive 得到的就是一个完整的 DatagramPacket,这里携带的二进制的字节数组,就是一个完整的应用层数据包

TCP 报头

首部长度

TCP 报头的长度

  • UDP 协议报头固定就是 8 个字节
  • 对于 TCP 来说,报头长度是可变的
    4 个比特位可表示的范围:
  • 0000~1111——>0x0~0xF——>0~15
  • 此处的长度单位是 4 字节,不是字节(所以范围是 0~60 字节)

保留(6 位)

虽然现在不用,但是先把这个东西申请下来,以备不时之需。用于考虑未来的可扩展性

  • 充分吸取了 UDP 的教训,UDP 的报文长度字段,是没法扩展的
  • 如果未来某一天,TCP 需要新增属性或者谋和属性的长度不够用,就可以把保留位拿出来,进行使用
  • TCP 的结构不需要发生太大的改变,这样的升级就会容易很多

关于“可扩展性”也是属于编程的时候需要考虑到的一点,毕竟写的代码不可能写一份就能持续地使用。对代码做出调整,做出修改,是非常普遍、常见的情况

但是,

选项

TCP 报头边长的主要原因。四个字节为一个单位

  • 可以有, 也可以没有
  • 可有一个,也可有多个
    通过“首部长度”确定报头有多长,如果是两个四个字节长度就是两个选项,三个四个字节长度就是三个选项,以此类推

序号

由于会出现“后发先至”的情况,所以需要通过编号,区分出数据的先后顺序

序号:表示的就是 TCP 数据报载荷中的第一个字节的序号,由于序号是连续递增,知道了第一个字节的序号,后续每个字节的序号也就知道了

  • 32 位/四字节,表示的范围是 0~42亿9千万0~4G
  • 因为 TCP 是面向字节流的,所以一个 TCP 数据报和下一个 TCP 数据报携带的数据,是可以直接进行拼装的
  • 比如要传输一个特别大的数据,传输过程中,本身就会通过多个TCP数据报来进行携带,这些TCP数据报彼此之间携带的载荷都是可以在接受方自动拼起来的
  • 这样就不像 UDP 存在传输的上限,使用 UDP 传输大数据,就需要考虑调用这一次 send 操作,参数是否超过了 64KB,超过了就不行
  • 使用 TCP 的话就没关系,可以调用一次 write,也可以调用多次 write。无论怎么进行 write,在网络传输和对端接收的角度来看是没有任何差别的
  • 如果多次 write,传输的总数据量超过上述的 4G 也没关系,这里的数据序号是可以再从 0 开始重新设置的

确认序号

确认序号的设定方式,和后发先至中发短信的例子,略有差别

  • TCP 序号不是按照“一条两条”来编排的,而是按照“字节”来编排的

TCP 的确认序号这里,填写的是 1001,接收方收到的数据的最后一个字节序号的下一个序号

  • 表示的含义是 <1001 的序号的数据都收到了(TCP 序号是连续增长的)
  • 对于应答报文来说,“确认序号”就会按照收到的数据的最后一个字节序号+1 的方式来填写
  • 并且六个标志位中,第二个标志位(ACK)会设为1
  • 普通报文的 ACK0,应答报文的 ACK1
  • 如果是普通报文,序号是有效的,确认序号是无效的;如果是应答报文,序号和确认序号都是有效的
  • 应答报文的序号是另一套编号体系,和传输数据的序号是不一样的
  • 应答报文默认情况下是不携带数据的


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
1月前
|
网络协议 大数据 网络架构
【TCP】确认应答、超时重传机制和TCP报头
【TCP】确认应答、超时重传机制和TCP报头
74 3
|
3月前
|
Java
java网络编程 UDP通信协议实现局域网内文件的发送和接收
java网络编程 UDP通信协议实现局域网内文件的发送和接收
java网络编程 UDP通信协议实现局域网内文件的发送和接收
|
5月前
用UDP协议实现发送接收的网络聊天室
用UDP协议实现发送接收的网络聊天室
37 0
|
6月前
|
前端开发 网络协议 JavaScript
如何在前端实现WebSocket发送和接收TCP消息(多线程模式)
请确保在你的服务器端实现WebSocket的处理,以便它可以接受和响应前端发送的消息。同时,考虑处理错误情况和关闭连接的情况以提高可靠性。
502 0
|
6月前
|
消息中间件 Kubernetes 网络协议
知识巩固源码落实之2:tcp服务端接收处理半包和粘包
知识巩固源码落实之2:tcp服务端接收处理半包和粘包
65 0
|
网络协议 网络架构
TCP协议报文,核心特性可靠的原因,超时重传详细介绍
TCP协议报文,核心特性可靠的原因,超时重传详细介绍
|
网络协议 算法 网络性能优化
TCP拥塞控制,拥塞窗口,携带应答,捎带应答,面向字节流,异常情况处理,最终完结弹
TCP拥塞控制,拥塞窗口,携带应答,捎带应答,面向字节流,异常情况处理,最终完结弹
|
网络协议 Unix Windows
确认应答机制与超时重发机制【TCP原理(笔记一)】
确认应答机制与超时重发机制【TCP原理(笔记一)】
420 0
|
网络协议 Java
UDP发送数据、接收数据及UDP通信程序练习
UDP发送数据、接收数据及UDP通信程序练习
293 0
|
缓存 网络协议 算法
计算机网络学习26:TCP/UDP对比区别、TCP流量控制、拥塞控制、超时重传时间的选择、可靠传输的实现
UDP: User Datagram Protocol 用户数据报协议 TCP: Transmission Control Protocol 传输控制协议 同时这里指的连接是指逻辑连接,而不是物理连接。
计算机网络学习26:TCP/UDP对比区别、TCP流量控制、拥塞控制、超时重传时间的选择、可靠传输的实现