当前位置: 首页 > article >正文

2.2.3 TCP—UDP-QUIC

文章目录

  • 2.2.3 TCP—UDP-QUIC
    • 1. TCP如何做到可靠性传输
      • 1. ACK机制
      • 2. 重传机制
      • 3. 序号机制
      • 4. 窗口机制
      • 5. 流量机制
      • 6. 带宽机制
    • 2. tcp和udp如何选择
      • 1. tcp和udp格式对比
      • 2. ARQ协议(Automatic Repeat reQuest,自动重传请求)
        • 1. ARQ协议的主要类型
        • 2. ARQ协议的关键技术
      • 3.RTT和RTO
      • 4. 流量控制
      • 5. 拥塞控制
      • 6. udp并发编程
    • 3. udp如何可靠,kcp协议在那些方面有优势
      • KCP能否比TCP有更高的带宽?
      • KCP协议的优势
      • 1. kcp使用
        • 1. 函数
        • 2. KCP工作流程
        • 3. KCP示例代码
    • 4. QUIC
      • 1. QUIC实现可靠传输的核心机制
      • 2. ​QUIC解决TCP的四大缺陷
      • 3. ​QUIC与HTTP/3的关系

2.2.3 TCP—UDP-QUIC

1. TCP如何做到可靠性传输

1. ACK机制

接收方在成功接收到数据后,会向发送方发送一个确认信号(ACK),告知发送方数据已正确接收。通过ACK机制,发送方可以确认数据是否成功到达接收方,从而决定是否需要重传。

2. 重传机制

重传机制是TCP确保数据可靠传输的核心。当发送方未收到ACK或检测到数据丢失时,会触发重传。主要包括:

  • 超时重传:发送方为每个数据段设置重传计时器(RTO),超时未收到ACK则重传。
  • 快速重传:发送方收到3个重复ACK后,立即重传丢失的数据段,无需等待超时。

3. 序号机制

TCP通过序号机制为每个数据段分配唯一的序列号(Sequence Number),接收方根据序号对数据段进行排序和重组。序号机制确保数据的有序性和完整性,避免数据丢失或乱序。

4. 窗口机制

窗口机制用于控制发送方的数据发送速率,避免接收方缓冲区溢出。主要包括:

  • 接收窗口(RWND)​:接收方告知发送方当前可接收的数据量。
  • 拥塞窗口(CWND)​:发送方根据网络拥塞情况动态调整发送速率。
  • 滑动窗口:发送方在窗口范围内连续发送数据,提高传输效率。

5. 流量机制

流量机制通过控制数据发送速率,避免网络拥塞和接收方过载。主要包括:

  • 流量控制:根据接收方的缓冲区大小动态调整发送速率。
  • 拥塞控制:通过慢启动、拥塞避免等算法,动态调整发送速率,避免网络拥塞。

6. 带宽机制

带宽机制用于优化网络资源利用率,确保数据传输的高效性。主要包括:

  • 带宽分配:根据网络状况和优先级合理分配带宽。
  • 带宽限制:通过流量整形和速率限制,避免带宽滥用。
  • 带宽监测:实时监测网络带宽使用情况,动态调整传输策略。

2. tcp和udp如何选择

  1. tcp 面向字节流
    TCP将数据视为连续的字节流,而不是独立的数据包。发送方和接收方之间建立连接后,数据以字节流的形式传输,接收方按顺序接收并重组数据。
    类似打电话

  2. udp 面向报文
    UDP将数据视为独立的数据报(报文),每个数据报都有明确的边界。发送方和接收方之间无需建立连接,数据报直接发送。
    类似发短信,每个信息之间是独立的

1. tcp和udp格式对比

特性TCPUDP
头部长度20字节(不含选项)8字节
可靠性可靠传输(确认、重传、排序机制)不可靠传输(无确认、重传机制)
连接性面向连接(需三次握手建立连接)无连接(直接发送数据报)
数据边界无边界(面向字节流)有边界(面向报文)
控制位有(SYN、ACK、FIN等)
流量控制有(窗口机制)
拥塞控制有(慢启动、拥塞避免等)
校验和强制可选
适用场景文件传输、网页浏览、电子邮件等视频流、语音通话、在线游戏等

可靠指的是可以正常收到而且是顺序收到,ARQ协议就是干这个的

2. ARQ协议(Automatic Repeat reQuest,自动重传请求)

ARQ协议通过确认(ACK)和重传机制,确保数据在传输过程中不丢失、不重复、不乱序

1. ARQ协议的主要类型

(1)停等ARQ(Stop-and-Wait ARQ)​
发送方每发送一个数据帧后,等待接收方的ACK。如果收到ACK,则发送下一个帧;如果超时未收到ACK,则重传当前帧
(2)回退N帧ARQ(Go-Back-N ARQ)​
发送方可以连续发送多个数据帧,无需等待ACK。如果某个帧丢失或损坏,发送方从该帧开始重传所有后续帧。
(3)选择性重传ARQ(Selective Repeat ARQ)​
发送方可以连续发送多个数据帧,接收方对每个帧单独确认。如果某个帧丢失或损坏,发送方仅重传该帧,而不影响其他帧。

2. ARQ协议的关键技术
  1. ​序号机制
    为每个数据帧分配唯一的序号,用于标识帧的顺序和检测丢失帧。

  2. ​超时机制
    发送方为每个帧设置超时计时器,超时未收到ACK则触发重传。

  3. ​滑动窗口
    通过滑动窗口控制发送方和接收方的缓冲区大小,优化数据传输效率。

3.RTT和RTO

RTO(Retransmission Timeout)​:重传超时时间,动态计算,基于RTT(Round-Trip Time,往返时间)。
​RTT测量:通过时间戳或ACK的到达时间计算RTT,并更新RTO。

4. 流量控制

对发送方发送速率的控制,称之为流量控制(发的过快就放缓存,再发的多就TM丢了,大量的丢包会极大着浪费网络资源,要保持接收双方动态稳定)

  1. 通信双方各有两个滑动窗口:
    ​接收窗口:用于接收数据。
    ​发送窗口(拥塞窗口)​:用于发送数据。
    接收窗口大小的通知称为窗口通告。
  2. ​接收窗口的动态调整

接收窗口的大小不是固定的,而是根据某种算法动态调整,以适应网络环境和发送窗口的变化。
3. ​接收窗口的优化

接收窗口并非越大越好。当窗口达到一定值后,继续增大不会显著减少丢包率,反而会增加内存消耗。因此,接收窗口的大小需要根据网络环境和发送窗口动态调整。
4. ​发送窗口与接收窗口的关系

发送窗口和接收窗口不一定相等。接收方在发送确认报文时会告知发送方其接收窗口大小,发送方据此调整发送窗口。
由于接收方在处理缓存区数据的同时发送确认报文,因此一般情况下,​接收窗口 ≥ 发送窗口。

5. 拥塞控制

在这里插入图片描述

  1. ​慢开始

​初始阶段:拥塞窗口(cwnd)从1开始,​指数增长​(每轮次翻倍)。
​触发条件:连接建立或检测到网络超时(超时视为严重拥塞)。
​阈值作用:初始慢开始阈值(ssthresh)决定何时切换至拥塞避免阶段

  1. ​拥塞避免(Congestion Avoidance)​

​线性增长:当cwnd ≥ ssthresh时,进入“加法增大”阶段,每轮次cwnd加1。
​目标:避免因窗口过快膨胀引发网络拥塞。

  1. ​快恢复(Fast Recovery)​

​触发条件:收到3个重复ACK​(轻度拥塞信号)。
​行为:
​TCP Reno:将cwnd减半(图中从24降至12),更新ssthresh为新值(12),并直接进入拥塞避免​(而非重新慢启动)。
​TCP Tahoe​(已废弃):直接重置cwnd=1并重新慢开始,效率较低。

6. udp并发编程

在这里插入图片描述

3. udp如何可靠,kcp协议在那些方面有优势

KCP能否比TCP有更高的带宽?

在网络通畅的情况下,KCP以10%-20%带宽浪费的代价,换取了比TCP快30%-40%的传输速度。

KCP协议的优势

  • 流量不一定最多
    KCP的传输速率可能低于TCP,但延迟更低,适合实时性要求高的场景。

  • RTO翻倍 vs 不翻倍

    • TCP超时计算是RTO×2,连续丢三次包后RTO变为×8,非常保守。
    • KCP在快速模式下RTO仅×1.5(实验证明1.5效果较好),显著提升传输速度。
  • 选择性重传 vs 全部重传

    • TCP丢包时会重传从丢失包开始后的所有数据(Go-Back-N)。
    • KCP采用选择性重传,仅重传真正丢失的数据包,减少冗余。
  • 快速重传

    • 使用快速重传时,无需等待RTO超时。
    • 示例:发送端发送1,2,3,4,5,收到ACK:1,3,4,5。当收到ACK3时,KCP知道2被跳过1次;收到ACK4时,知道2被跳过2次,立即重传2号包。
    • 参数:fastresend = 2
  • 延迟ACK vs 非延迟ACK

    • TCP为了充分利用带宽,延迟发送ACK,导致RTT时间计算偏大,延长丢包判断过程
    • KCP的ACK延迟发送可调节,灵活性更高
  • UNA vs ACK+UNA

    • ARQ模型有两种响应方式:UNA(此编号前所有包已收到,如TCP)和ACK(该编号包已收到)。
    • 仅用UNA会导致全部重传,仅用ACK则增加网络负载
    • KCP协议中,除单独的ACK包外,所有包都携带UNA信息,结合两者优势
      比如:
      发送端发送序列号1、2、3、4、5。
      接收端收到1、2、4、5,丢失3。
      接收端发送UNA=3(表示1、2已接收),并发送ACK=4、ACK=5(确认4、5已接收)。
      发送端根据UNA=3知道3丢失,立即重传3,而无需重传4、5。
  • 非退让流控

    • KCP正常模式与TCP一样使用公平退让法则,发送窗口大小由以下四要素决定:
      1. 发送缓存大小
      2. 接收端剩余接收缓存大小
      3. 丢包退让 (当检测到丢包时,减少发送窗口大小,避免进一步加剧网络拥塞。)
      4. 慢启动
    • 在传送及时性要求高的小数据场景中,可通过配置跳过后两步(​丢包退让和慢启动机制会降低发送速率,导致传输延迟增加),仅用前两项控制发送频率。

KCP通过牺牲少量带宽,显著提升了传输速度和实时性,特别适合高延迟、高丢包网络环境(如实时音视频、竞技类网游)。

1. kcp使用

在这里插入图片描述

1. 函数
  1. ​**kcp_create**
  • 功能:创建KCP对象。
  • 参数
    • conv:会话ID,用于标识KCP连接。
    • user:用户自定义数据,通常为NULL。
  • 返回值:KCP对象指针。
  • 示例
    ikcpcb *kcp = ikcp_create(conv, user);
    
  1. kcp_update
    ​功能:更新KCP状态,触发内部定时任务(如超时重传、窗口更新等)。
    ​参数:
    kcp:KCP对象指针。
    current:当前时间戳(毫秒)。
    ​示例:
ikcp_update(kcp, current);
  1. kcp_send
    ​功能:发送数据。
    ​参数:
    kcp:KCP对象指针。
    buffer:待发送的数据缓冲区。
    len:数据长度。
    ​返回值:成功返回0,失败返回负值。
    ​示例:
int ret = ikcp_send(kcp, buffer, len);
  1. kcp_input
    ​功能:接收数据并处理(如解析KCP协议头、更新ACK等)。
    ​参数:
    kcp:KCP对象指针。
    data:接收到的数据缓冲区。
    size:数据长度。
    ​返回值:成功返回0,失败返回负值。
    ​示例:
int ret = ikcp_input(kcp, data, size);
  1. kcp_recv
    ​功能:从KCP接收缓冲区中读取应用层数据。
    ​参数:
    kcp:KCP对象指针。
    buffer:接收数据的缓冲区。
    len:缓冲区长度。
    ​返回值:实际读取的数据长度。
    ​示例:
int len = ikcp_recv(kcp, buffer, sizeof(buffer));
2. KCP工作流程
  1. ​初始化阶段
    调用kcp_create创建KCP对象。
    设置KCP参数(如窗口大小、超时时间等)。
  2. ​数据发送流程
    应用层调用kcp_send发送数据。
    KCP内部将数据分片,添加KCP协议头(24字节)。
    调用output回调函数发送数据包。
    定时调用kcp_update触发重传和窗口更新。
  3. ​数据接收流程
    网络层接收到数据包,调用kcp_input处理。
    KCP解析协议头,更新ACK和窗口状态。
    应用层调用kcp_recv读取数据。
  4. ​定时任务
    定期调用kcp_update,处理超时重传、窗口更新等任务。
3. KCP示例代码
  1. ​初始化KCP
ikcpcb *kcp = ikcp_create(conv, user);
ikcp_wndsize(kcp, 128, 128); // 设置窗口大小
ikcp_nodelay(kcp, 1, 10, 2, 1); // 启用快速模式
  1. ​发送数据
char buffer[1024];
int len = sprintf(buffer, "Hello, KCP!");
ikcp_send(kcp, buffer, len);
  1. ​接收数据
char buffer[1024];
int len = ikcp_recv(kcp, buffer, sizeof(buffer));
if (len > 0) {
    printf("Received: %s\n", buffer);
}
  1. ​定时更新
while (1) {
    sleep_ms(10);
    ikcp_update(kcp, current_ms());
}
  1. 集成
#include "ikcp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>

// 回调函数:发送 KCP 数据包
int output(const char *buf, int len, ikcpcb *kcp, void *user) {
    int sockfd = *(int*)user;
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(8888);
    inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
    sendto(sockfd, buf, len, 0, (struct sockaddr*)&addr, sizeof(addr));
    return 0;
}

int main() {
    // 创建 UDP 套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        perror("socket");
        exit(1);
    }

    // 初始化 KCP 对象
    ikcpcb *kcp = ikcp_create(0x11223344, &sockfd);
    ikcp_wndsize(kcp, 128, 128); // 设置窗口大小
    ikcp_nodelay(kcp, 1, 10, 2, 1); // 启用快速模式
    ikcp_setoutput(kcp, output); // 设置回调函数

    // 发送数据
    char send_buffer[1024];
    int send_len = sprintf(send_buffer, "Hello, KCP!");
    ikcp_send(kcp, send_buffer, send_len);

    // 接收数据
    char recv_buffer[1024];
    while (1) {
        // 接收网络数据
        struct sockaddr_in addr;
        socklen_t addr_len = sizeof(addr);
        int recv_len = recvfrom(sockfd, recv_buffer, sizeof(recv_buffer), 0, (struct sockaddr*)&addr, &addr_len);
        if (recv_len > 0) {
            // 处理 KCP 协议包
            ikcp_input(kcp, recv_buffer, recv_len);

            // 读取应用数据
            int len = ikcp_recv(kcp, recv_buffer, sizeof(recv_buffer));
            if (len > 0) {
                printf("Received: %s\n", recv_buffer);
            }
        }

        // 定时更新 KCP 状态
        ikcp_update(kcp, current_ms());
        usleep(10000); // 10ms
    }

    // 释放 KCP 对象
    ikcp_release(kcp);
    close(sockfd);
    return 0;
}

4. QUIC

1. QUIC实现可靠传输的核心机制

  1. ​Packet Number严格递增

每个数据包分配唯一且严格递增的序列号(Packet Number),即使重传数据包也会使用新序列号。

  • ​优势:
    消除TCP重传歧义问题,精确计算RTT(往返时间),优化超时重传策略。
    支持乱序确认,避免因单个数据包丢失阻塞后续传输(解决队头阻塞)。
  1. ​Frame Header设计

每个数据包包含多个Frame,通过以下字段保证数据顺序和可靠性:
​Stream ID:标识不同的并发数据流(类似HTTP/2的Stream)。
​Offset:标记数据在流中的偏移量(类似TCP的序列号)。
​Length:数据长度。

  • ​作用:通过Stream ID + Offset唯一标识数据内容,即使重传数据包的Packet Number不同,也能正确重组数据。
  1. ​流量控制

​Stream级流量控制:每个Stream独立维护滑动窗口,互不影响。
​Connection级流量控制:限制所有Stream的总数据量,防止整体过载。

  • ​实现方式:
    通过WINDOW_UPDATE帧动态调整窗口大小。
    通过BLOCKED帧通知发送方流量阻塞。
  1. ​拥塞控制改进

默认使用TCP的Cubic算法,同时支持BBR、PCC等算法。

  • ​优势:
    在应用层实现,无需内核支持,灵活升级算法。
    可为不同应用定制拥塞策略(如视频流与文件传输使用不同算法)。

2. ​QUIC解决TCP的四大缺陷

  1. ​协议升级困难

TCP协议栈内置于操作系统,升级依赖内核更新;QUIC在应用层实现,通过更新浏览器或应用即可部署新特性。
2. ​连接建立延迟

​1-RTT握手:QUIC将TLS 1.3集成到协议中,首次连接仅需1个RTT完成密钥协商和连接建立。
​0-RTT恢复:会话恢复时可直接发送数据,无需握手。
3. ​队头阻塞问题

​Stream独立滑动窗口:每个HTTP请求(Stream)拥有独立窗口,某个Stream丢包不影响其他Stream。
​乱序确认:基于Packet Number和Offset,允许接收方乱序确认数据包。
4. ​网络迁移需重建连接

​连接ID标识:QUIC通过连接ID(而非IP+端口)标识连接,网络切换(如4G转WiFi)时无需重建连接,实现无缝迁移。

3. ​QUIC与HTTP/3的关系

HTTP/3基于QUIC协议,将传输层从TCP替换为QUIC,彻底解决HTTP/2的TCP队头阻塞问题。
QUIC在UDP报文头部与HTTP数据之间添加三层头部:

  1. ​Long/Short Packet Header:管理连接ID与数据包编号。
  2. ​QUIC Frame Header:标识Stream及数据偏移。
  3. ​HTTP/3帧:承载实际应用数据。

http://www.kler.cn/a/587405.html

相关文章:

  • 星越L_内后视镜使用讲解
  • 电子招采软件系统,如何实现10年可追溯审计
  • Spring、Spring Boot、Spring Cloud 的区别与联系
  • 矫平机:解锁精密制造的工业之手
  • (学习总结28)Linux 基本命令3
  • odbus TCP转Modbus RTU网关快速配置案例
  • 深入理解Spring MVC:构建灵活的Web应用
  • python3GUI--模仿安卓桌面 By:PyQt5(附下载地址)
  • 破碎的誓言
  • 【打卡D6】二分法
  • 计算机网络-TCP/IP协议族
  • Vue:收集表单数据过滤器
  • 深入理解 HTML 中的<div>和元素:构建网页结构与样式的基石
  • phpstudy+phpstorm+xdebug【学习笔记】
  • IDEA集成git,项目的克隆,远程仓库中文件的添加删除
  • AI Agent 时代开幕-Manus AI与OpenAI Agent SDK掀起新风暴
  • STL标准库
  • C++20中的`std::endian`:深入理解大端/小端/本地字节序
  • Ubuntu 20.04使用阿里源并更新glibc到2.35版本
  • X86 RouterOS 7.18 设置笔记八:策略路由及DNS劫持