一、QUIC协议

QUIC ,即 快速UDP网络连接 ( Quick UDP Internet Connections ), 是由 Google 提出的实验性网络传输协议 ,位于 OSI 模型传输层。 QUIC 旨在解决 TCP 协议的缺陷,并最终替代 TCP 协议, 以减少数据传输,降低连接建立延 迟时间,加快网页传输速度。

标准文档地址:https://quicwg.org/base-drafts/rfc9000.html

1. QUIC框图

1.1 为什么QUIC在应用层实现

  • 新的传输层协议通常会经过严格的设计,分析和评估可重复的结果,证明候选协议对 现有协议的正确性和公平性,开发新的传输层协议和它在操作系统进行广泛部署之间 通常需要花费数年的时间。
  • 再者,用户与服务器之间要经过许多防火墙、NAT(地址转换)、路由器和其他中间设 备,这些设备很多只认TCP和UDP。如果使用另一种传输层协议,那么就会有可能无法 建立连接或者报文无法转发,这些中间设备会认为除TCP和UDP协议以外的协议都是不 安全或者有问题的。

1.2 QUIC协议术语

QUIC连接:CLient和Server之间的通信关心,Client发起连接,Server接收连接

流(Stream):一个QUIC连接内,单向或者双向的有序字节流。一个QUIC连 接可以同时包含多个Stream

帧(Frame):QUIC连接内的最小通信单元。一个QUIC数据包(packet)中的 数据部分包含一个或多个帧

1.3 QUIC和TCP对比

2. QUIC报文格式

2.1 QUIC数据包格式

  • Header是明文的,包含4个字段:Flags、Connection ID、QUIC Version、Packet Number
  • Data 是加密的,可以包含 1 个或多个 frame,每个 frame 又分为 type 和 payload, 其中 payload 就是应用数据

2.2 QUIC Stream帧

数据帧有很多类型:Stream、ACK、Padding、Window_Update、Blocked 等,这里重点介 绍下用于传输应用数据的 Stream 帧。

Frame Type:帧类型,占用1个字节

  1. Bit7:必须设置为 1,表示 Stream 帧
  2. Bit6:如果设置为 1,表示发送端在这个 stream 上已经结束发送数据,流将处于半关闭状态
  3. Bit5:如果设置为 1,表示 Stream 头中包含 Data length 字段
  4. Bit4-2:表示 offset 的长度。000 表示 0 字节,001 表示 2 字节,010 表示 3 字节,以此类推
  5. Bit1-0:表示 Stream ID 的长度。00 表示 1 字节,01 表示 2 字节,10 表示 3 字节,11 表示 4 字 节

Stream ID:流 ID,用于标识数据包所属的流。后面的流量控制和多路复用会涉及到。

Offset:偏移量,表示该数据包在整个数据中的偏移量,用于数据排序。

Data Length: 数据长度,占用 2 个字节,表示实际应用数据的长度.

Data: 实际的应用数据

3. QUIC的特点

  1. 连接建立低时延
  2. 多路复用
  3. 无队头阻塞
  4. 灵活的拥塞控制机制
  5. 连接迁移
  6. 数据包头和包内数据的身份认证和加密
  7. FEC前向纠错
  8. 可靠性传输
  9. 其他

3.1 连接建立低延时

3.1.1 典型TCP+TLS连接

  1. 首先,执行三次握手,建立TCP连接(蓝色部分)
  2. 然后,执行TLS握手,建立TLS连接(黄色)
  3. 此后开始传输业务数据

注意到,三次握手中的 ACK 包与 handshake 合并在一起发送。 这是 TCP 实现中使用的 延迟确认 技术, 旨在减少协议开销,改善网络性能。

客户端和服务器之间要进行多轮协议交互,才能建立 TLS 连接,延迟相当严重。 平时访问 https 网站明显比 http 网站慢,三次握手和 TLS 握手难辞其咎。

3.1.2 首次连接对比

  • 共3RTT:TCP+TLS1.2中: TCP三次握手建立连接需要1个RTT;TLS需要2个RTT完成 身份验证;传输数据
  • 共2RTT:TCP+TLS1.3中: TCP三次握手建立连接需要1个RTT;TLS需要1个RTT完成 身份验证;传输数据
  • 共1RTT: 首次QUIC连接中,Client 向 Server 发送消息,请求传输配置参数和加 密相关参数;Server 回复其配置参数;传输数据

3.1.2 再次连接对比

  • 再次连接的概念:Client已经访问过Server,在本地存放了Cookie。
  • 2RTT:TCP+TLS1.2中: TCP三次握手建立连接需要1个RTT;TLS需要1个RTT完成身份 验证(由于缓存的存在,减少1RTT);传输数据
  • 1RTT:TCP+TLS1.3 中: TCP三次握手建立连接需要1个RTT;传输数据
  • 0RTT:在客户端与服务端的再次QUIC连接中,Client 本地已有 Server 的全部配置 参数(缓存),据此计算出初始密钥,直接发送加密的数据包。

3.2 多路复用

在一个网页里面总是会有多个数据要传输,总是希望多个数据能够同时传输,以此 来提高用户的体验。

3.2.1 HTTP1.1

每个TCP连接同时只能处理一个请求—响应,为了提高响应速度,需要 同时创建多个连接,但是多个连接管理比较复杂。

3.2.2 HTTP2

  • 每个TCP连接里面有多个逻辑上独立的多个流(stream)
  • 每个流可以传输不同的文件数据
  • 解决了HTTP1一个连接无法同时传输多个数据的问题
  • 缺点:容易出现队头阻塞问题

3.2.3 QUIC(HTTP3)

  • 借鉴了HTTP2中流的概念
  • 流之间互相独立,即不同流之间的数据之间交付顺序无关(如果 stream2的数据丢失,只会影响排在stream2后面的数据,stream1和 stream3的数据不会被影响)
  • 建立在UDP之上,没有依赖性

3.3 无队头阻塞

HTTP/2会出现队头阻塞问题,而在基于QUIC的HTTP/3中则很好地解决这一问题。

  • UDP中的各个数据报独立,基于UDP的QUIC中的各个stream独立
  • 即使stream2里有一个包丢失,因为stream之间互相独立无关联,所以不会 阻塞stream3、stream4,依然可以交付给上层

3.4 灵活的拥塞控制和机制

TCP 的拥塞控制实际上包含了四个算法:慢启动,拥塞避免,快速重传,快速恢复。

  • New Reno:基于丢包检测
  • CUBIC:基于丢包检测
  • BBR:基于网络带宽

QUIC协议可以自己设置或实现拥塞控制协议。

QUIC 协议当前默认使用了 TCP 协议的 Cubic 拥塞控制算法。 这个机制还是可插拔的,能够非常灵活地生效,变更和停止,可以根据场景来切换不同的方法。

QUIC协议在用户空间实现,应用程序不需要停机和升级就能实现拥塞控制 的变更,在服务端只需要修改一下配置,reload 一下,完全不需要停止服务 就能实现拥塞控制的切换。甚至可以为每一个请求都设置一种拥塞控制算法。

而TCP在内核态,其拥塞控制难以进行修改和升级。

3.5 连接迁移

连接迁移:当客户端切换网络时,和服务器的连接并不会断开,仍然可以正常通信。

对于 TCP 协议而言,这是不可能做到的。因为 TCP 的连接基于 4 元组:源 IP、源端口、 目的 IP、目的端口,只要其中 1 个发生变化,就需要重新建立连接。

但 QUIC 的连接是 基于 64 位的 Connection ID,网络切换并不会影响 Connection ID 的变化,连接在逻辑上 仍然是通的。IP地址或者端口号发生变化时,只要ID不变,依然能够维持原有连接,上层业务逻辑感 知不到变化,不会中断。

客户端的Connection ID是唯一的。

3.6 数据包头和包内数据的身份认证和加密

相比于TCP,QUIC的安全性是内置的,也就是说是必须的。

在恶意环境下性能与TLS类似,友好环境下优于TLS,因为TLS使用一个会话密钥, 如果这个密钥被截获的话就不能保证之前数据的安全性。

而QUIC使用两个密钥——初始密钥和会话密钥,并且QUIC提供密码保护,TLS不提供。

除此之外,QUIC的包头经过身份认证,包内数据是加密的。这样如果QUIC数据 被恶意修改的话接收端是可以发现的,降低了安全风险。

而且数据加密之后,可以通过像防火墙或者nat这些中间件。

两个密钥的生成可参考:https://blog.csdn.net/chuanglan/article/details/85106706

3.7 FEC前向纠错

FEC是Forward Error Correction前向错误纠正的意思,就是通过多发一些冗余的包, 当有些包丢失时,可以通过冗余的包恢复出来,而不用重传。这个算法在多媒 体网关拥塞控制有重要的地位。QUIC的FEC是使用的XOR的方式,即发N + 1个包, 多发一个冗余的包,在正常数据的N个包里面任意一个包丢了,可以通过这个冗 余的包恢复出来,使用异或可以做到切换网络操持连接。

3.8 可靠性传输

QUIC 是基于 UDP 协议的,而 UDP 是不可靠传输协议,那 QUIC 是如何实现可靠传输的呢?

可靠性传输有2个重要特点:

  1. 完整性:发送端发出的数据包,接收端都能收到
  2. 有序性:接收端能按序组装数据包,解码得到有效的数据

3.8.1 有序性设计

QUIC每个Stream帧中都有offset字段和StreamID字段,这使得乱序接收的数据能够有序排列。

3.8.2 完整性设计

发送端通过包号(PKN)和确认应答(SACK)确认发送数据完整性。

  1. 客户端:发送 3 个数据包给服务器(PKN = 1, 2,3)
  2. 服务器:通过 SACK 告知客户端已经收到了 1 和 3,没有收到 2
  3. 客户端:重传第 2 个数据包(PKN=4)

尽管QUIC会重传数据包,但是新的数据包的PKN的继续递增的,即之前发送的数据包(PKN=2)和重传的 数据包(PKN=4),虽然数据一样,但包号不同。这也解决了TCP中,原始包和重传包的序列号一样带来的重传歧义问题。

由于TCP原始包和重传包的序列号是一样的,客户端不知道服 务器返回的 ACK 包到底是原始包的,还是重传包的。但 QUIC 的原始包和重传包的序列号是不同的,也就可以判 断 ACK 包的归属。

4. QUIC开源库

  1. google的gquic 起源最早, 不过它不是单独项目, 代码在chromium项目里边, 用的 是c++写的, 可能不是很适合。
  2. 微软的msquic, 用c写的, 跨平台, 不过开始得比较晚。
  3. facebook的quic 用的是c++写的. 暂不考虑。
  4. nginx的quic 没有自带client, 但它可与ngtcp2联调。
  5. litespeed的 lsquic 是基于MIT的, 开始于2017年, 还算比较稳定, 用c语言编写, 各 主流平台都有通过测试, 有server/client/lib, 它用于自家的各种产品, 暂时看上去 是最合适的。
  6. ngtcp2, 它是一个实验性质的quic client, 很简洁, 实现了几乎每一版ietf draft. 从 代码简洁性上来看, 它无疑是最好的。目前srs流媒体服务器、curl等开源项目有 基于ngtcp2做二次开发。

4.1 ngtcp2

  1. https://github.com/ngtcp2/ngtcp2
  2. 采用C语言实现
  3. 范例client和server使用了c++17的特性,我们需要升级编译器(比如, clang >= 8.0, 或 gcc >= 8.0)
  4. 编译文档见《QUIC开源库安装和实践.pdf》

参考博客:UDP可靠性传输-QUIC - 幻cat - 博客园

UDP可靠性传输-QUIC相关推荐

  1. android 判断byte值_Android开发之UDP可靠性传输

    轩羽:Android开发之UDP​zhuanlan.zhihu.com 在这一篇文章里,小编说到UDP是不可靠的,故,我们要自己写一套协议,来使UDP实现可靠性传输,这里,小编和小编的小伙伴一起,写了 ...

  2. UDP可靠性传输KCP实现原理和应用

    一.为什么要做UDP可靠性传输? UDP与TCP的区别: TCP是为流量设计的(每秒可以传输多少KB的数据),因此在刚启动的时候会尽量少带宽,讲究的时候充分利用带宽. 可靠性UDP设计目的是解决:延迟 ...

  3. 【KCP】UDP可靠性传输

    1 如何做到可靠性传输 ◼ ACK机制 ◼ 重传机制 ◼ 序号机制 3 2 1 ->2 3 1 ◼ 重排机制 2 3 1 ->3 2 1 ◼ 窗口机制 Tcp不用我们管 可靠性udp 5种 ...

  4. UDP可靠性传输协议(QUIC)

    目录 UDP与TCP对比 可靠性机制 ACK机制 重传机制 流控控制 序号机制 重排机制 窗口机制 UDP可靠性设计 UDP窗口流控 KCP(出于实时性考虑) QUIC 简述 优点 缺点 报文格式 建 ...

  5. tcp重复的确认_TCP如何实现可靠性传输

    1.UDP与TCP的区别 TCP(TransmissionControl Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议. UDP是User Datagram P ...

  6. TCP如何实现可靠性传输

    1.UDP与TCP的区别 TCP(TransmissionControl Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议. UDP是User Datagram P ...

  7. 基于UDP的可靠传输——QUIC 协议

    一.UDP协议 UDP用户数据报协议,非连接的协议,传输数据之前源端和终端不建立连接,当它想传送时直接去抓取来自应用程序的数据,并尽可能快地把它扔到网络上. UDP传输协议的特点 UDP无连接,时间上 ...

  8. UDP与TCP对比,TCP保证可靠性传输的详细说明

    目录 1 UDP 2 TCP 2.1 TCP协议如何保证可靠传输 2.2 流量控制 2.2.1 TCP的滑动窗口 2.3 拥塞控制 2.3.1 慢开始 2.3.2 拥塞避免 2.3.3 快重传 2.3 ...

  9. C++TCP和UDP属于传输层协议

    TCP和UDP属于传输层协议.其中TCP提供IP环境下的数据可靠传输,它事先为要发送的数据开辟好连接通道(三次握手),然后再进行数据发送:而UDP则不为IP提供可靠性,一般用于实时的视频流传输,像rt ...

最新文章

  1. CString类的用法总结
  2. 从文件中读出数据显示在表格中_玩转表格:如何在Word表格中进行数据计算?...
  3. Qt ToolBar工具栏里同时显示图标和文字
  4. 什么是5G NR技术?一文带你深入了解5G NR技术
  5. 简单排序(插入排序法)
  6. Javascript闭包简单理解
  7. 网络营销教程—SEO 第五章 单面页最佳优化
  8. 2022年电子电路铜箔行业上下游产业链分析预测及市场规模供需平衡度研究
  9. [转]真正了解CSS3背景下的@font face规则
  10. 根据名称获取对应的拼音码首字母大写
  11. 项目成本管理-案例分享
  12. Gary Marcus:因果熵理论的荒诞和认知科学带给AI的11个启示 | 文末赠书
  13. linux最新bbr加速,CentOS 7.8 安装BBR加速
  14. 数据结构【一轮复习】---绪论(王道+天勤)
  15. 三步使用Docker容器创建RoboCup仿真2D环境
  16. 实战ssl-bump,实现squid的url过滤功能
  17. Informatica PowerCenter工作流管理系统
  18. DynamicPDF HTML TO PDF 转换器
  19. 解决“No input file specified”的问题
  20. 异地两个服务器延迟怎样降低,网络延迟怎么解决?教你两个有效的解决方法

热门文章

  1. 南京师范大学计算机录取人数,南京师范大学2018年自主招生计划及招生人数,录取统计情况分析!...
  2. ESI ProCAST 2018铸造仿真分析视频教程
  3. 通过用户名称获取微博id
  4. 植树造林,让地球降温还是升温?
  5. 疯狂java讲义第六章课后第4题答案
  6. 三毛作品集——在线阅读
  7. java jtextfield 改变_java – 如何更改JTextField的值?
  8. 客户机win10设置共享目录
  9. JS实现城市选择(详细讲解,步骤清晰)
  10. Unix/Linux编程:进程间通信(IPC)总结