因为想使用下quic协议,所以开源框架中选了lsquic,C语音实现,支持客户端和服务端,然后文档也是开源框架中较为丰富的。支持QUIC V1、Draft-29、27,Q043,Q046及Q050。 对应github的commit是:df67278304ce 。V3.03版本之后两个commit。
1、lsquic特征与架构
1.1、特征
- DPLPMTUD,一种在某一特定网络路径中探测单次能发送最大的UDP包大小的方法,因为QUIC是自己实现打包的故用这个方法能提升性能;
- ECN,显式拥塞通知;
- Spin bits,运行网络监控者计算链接的RTT;
- Path migration, 网络路径迁移(变更)
- NAT rebing,对端地址因为NAT等中间网络设备而变更了地址
- Push promises,PUSH_PROMISE帧,用于在发送者打算初始化流之前通知对端
- TLS Key updates
- Extensions,包括http3的能力,Datagrams,丢包率计算, ACK确认延迟(用于提高吞吐率)
1.2 、架构
lsquic本身不提供socket发送和接收数据、也没有固定的event事件机制,这部分都需要使用者自己实现,通过注册回调函数的方式来实现。
2、概念
2.1、Egine
Egine用于管理连接(connection)、处理收包及发包调度。Egine可初始化为客户端的Egine或服务端Egine。如果我们的程序兼有客户端和服务端身份,则需要初始化两个Egine,一个为client的,一个为server的。
2.2、Connection
一个连接可以携带一个或多个流(stream),保证可靠的包传输并且处理quic协议的细节。在客户端程序中一个连接通过函数调用创建,而在服务端只有在握手成功后业务编程的用户才能获取到链接实例。
2.3、 stream
流用于发送我们需要发送的业务数据,不会单独存在,必须存在于连接中。流是双向的,通常和请求/应答相关。
3、初始化流程
概括的看初始化流程如下,客户端流程多一个connect操作 非lsquic初始化流程但是很重要的两个流程是socket初始化以及boring ssl的初始化,下篇在具体说一下。
3.1、stream和connection的回调函数列表
stream和connection回调函数是lsquic和用户业务代码交互的方式,存储在lsquic_stream_if结构体里面,该结构体中有些函数是必须实现的,如连接和流创建和销毁,数据读取和发送的函数,如下
3.2、Engine配置
Egine的配置信息存储在lsquic_engine_api中,包括回调函数及参数配置,其中有一些必须由用户实现的,如下: 可以在Engnie中指定使用quic协议的版本。
3.3、connection、stream创建流程(客户端为例)
3.4、收发数据的流程
3.4.1、收数据流程
数据刚从socket读取出来时还是加密的quic数据只有经过lsquic_stream_read之后才是我们最终所要获取的数据流。
3.4.2 、数据发送流程
4、参考
《1》、lsquic tutorial
|