QUIC协议学习及源码浅析(基于python)

Ruqiu_ 2022-01-19 22:08:34
加精

一.QUIC简介

       QUIC协议全称Quick UDP Internet Connection 技术,即快速 UDP 互联网连接,该协议由Google 开发,是工作在传输层的网络传送协议,目前传输层协议主要是 TCP 和 UDP, QUIC 是在 UDP 协议的基础上改进。 QUIC 相对于以往的传输层协议有着众多优点:改进了拥塞控制、可以更快地进行连接的建立、多路复用不会出现对头阻塞的情况、使用UUID 作 为连接标记可以更方便地对连接进行迁移等。

                                                               

(图引自《浅谈 QUIC 协议原理与性能分析及部署方案》-by 周陆军)

       与传输层的另一个主流协议传输控制协议进行对比:

       1.在连接建立上,传输控制协议( TCP) 的连接建立过程被形象地叫做“3 次握手”,这是由于TCP在传输层负责提供“可靠性” 传输,3次握手的过程如下: 第1次握手是由客户端向服务端 发出,申请建立与服务器的连接; 第 2次握手由服务端发出,告知客户端收到请求; 第3次握手是客户端确认建立连接以保证可靠性。显然,3次握手的流程为了可靠而涉及到多次的包传输,因此需要多个往返时间,这种场景无法满足实时通信的要求。而QUIC则更加能够升任实施交付的场景,因为QUIC协议建立连接不需要多个RTT( 往返时间) ,实现了零往返时间连接。由于QUIC协议基于 UDP协议,因此 QUIC 在建立连接的时候会携带一次会话中所需要的完整参数,这使得 QUIC 的连接是 0RTT 的: 不会为了可靠性去确认已发送的数据包。 这个“0RTT 连接”的特性优化了参与会话的各个终端之间连接建立的速度。

      2.为了保证数据包在传输过程中的安全性,传统 HTTP 协议使用了TLS 作为 TCP 的 安全附加层,因此这个过程其实包括了 TCP 的 3 次握手和 TLS 等多次 RTT. 而在 QUIC 协议中,其内置了TLS为客户端进行数据完整性校验和隐私数据防护,这使得 QUIC 协议既保证了安全加密的同时,还在传输速度上更胜一筹。

      3.在会话标识上,TCP 协议通过五元组进行标识,5 个元素组成集合用以保证每个会话都有一个唯一标识,它包括: 目标IP地址、源IP地址、目标端口号、源端口号、传输层协议。而 QUIC 的会话标识则更加有效便捷: 只需要公共包头和一个唯一标记 ID,这样一来 QUIC 协议便有了以下特性: 连接转移,由于标识ID可以被保存,因此一个连接可以在端的网络发生状态时进行连接转移,比如实现无缝的网络切换。

      4.NAT重绑,在目前 NAT 广泛应用的背景下,NAT 其实对实时通信 P2P 连接造成了障碍,因此实时音视频通信时需要通过 NAT 穿透技术建立连接,这时候会出现 NAT 竞争的情况。当多个端进行抢占NAT出口时,需要重新绑定端口,这时候 QUIC 的 NAT 重绑特性就显得尤其重要。

      5.复用技术:TCP协议存在队头阻塞问题,也就是下个请求必须在前一个请求返回后才能发出,导致带宽无法被充分利用,后续请求被阻塞。HTTP 1.1 尝试使用流水线(Pipelining)技术,但先天 FIFO(先进先出)机制导致当前请求的执行依赖于上一个请求执行的完成,容易引起队头阻塞,并没有从根本上解决问题;QUIC 使用的 Packet Number 单调递增的设计,可以让数据包不再像 TCP 那样必须有序确认,QUIC 支持乱序确认,当数据包 Packet N 丢失后,只要有新的已接收数据包确认,当前窗口就会继续向右滑动。待发送端获知数据包 Packet N 丢失后,会将需要重传的数据包放到待发送队列,重新编号比如数据包 Packet N+M 后重新发送给接收端,对重传数据包的处理跟发送新的数据包类似,这样就不会因为丢包重传将当前窗口阻塞在原地,从而解决了队头阻塞问题。

                                                 

                                                                                   (图引自《科普:QUIC 协议原理分析》) 

 

二.QUIC协议配置及简单例程运行

     本次实验使用aioquic进行,aioquic是一个用python实现的QUIC网络库

     2.1实验环境

       操作系统 Windows

       Python版本:3.8.8

     2.2环境配置:

       安装Quicpython实现网络库aioquic:

       安装aioquic库的运行依赖:

       获取aioquic库源码以及例程源码

     2.3示例运行:

       运行服务端例程监听:

       运行客户端例程发送quic包至客户端:

      服务端响应及连接关闭:

三.QUIC主功能源码简析:

        初始连接设定__init__():分别根据端的属性来配置quic协议的连接设置,若为客户端则不应设置初始目标连接ID,丢包重发资源ID。服务端必须设置SSL证书与密钥,初始目标连接ID等

          建立连接connect:发起TLS握手仅调用客户端和一段时间。其中addr:远程端的网络地址,now:当前时间。

        切换连接change_connection_id:切换到下一个可用的连接ID并退出前一个。

        关闭连接close:关闭连接并且保存连接关闭的原因以及其可读形式。

          检索需要发送的数据:datagrams_to_send():在建立或者切换连接后调用,返回需要发送的“(数据,addr`(数据,addr`元组,以及需要发送的网络地址。

          事件获取函数next_event():从事件缓冲区检索下一个事件。如果没有缓冲的事件,则返回`none`

          捕获数据报receive_datagram():收到并处理数据报,保存收到数据报的网络地址,当前时间。

          发送数据:以数据报、流的现实发送数据。

300

...全文
3868 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

571

社区成员

发帖
与我相关
我的任务
社区描述
软件工程教学新范式,强化专项技能训练+基于项目的学习PBL。Git仓库:https://gitee.com/mengning997/se
软件工程 高校
社区管理员
  • 码农孟宁
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧