网络协议:TCP/UDP/KCP 可靠传输全解


一、如何做到可靠传输

  1. ACK机制(确认机制)
    对方收到数据后发“收到”确认,没确认就可能丢了。

  2. 重传机制:重传策略
    没收到确认就重新发送,什么时候重发、重发几次由策略决定。

  3. 序号机制
    每个数据块编号,避免顺序错乱、重复或遗漏。

  4. 重排机制
    如果乱序收到,就按编号排回正确顺序。

  5. 窗口机制
    一次只发部分数据,等收到确认再继续发,避免发送太快。

    • 流量控制
      根据对方接收能力调整发送速度,防止对方“吃不消”。

    • 带宽有限
      网络通道有限,发太快可能导致拥堵和丢包。


二、TCP 与 UDP 协议

2.1 TCP 与 UDP 对比

在这里插入图片描述
报文传输:
sendto(hello) ----> recvfrom 返回 hello
sendto(GuLu) ----> recvfrom 返回 GuLu
报文传输的时候,要有足够的空间读取整个报文,否则超出的部分就会丢失

字节流传输:
send(hello)
send(GuLu) ----> recv 可能返回 helloGuLu

2.1.1 报文传输(UDP)

  • 每次发送的是一个完整的报文(数据包)
    👉 类似“一次寄一个快递包裹”

  • sendto() 发送,用 recvfrom() 接收
    👉 每次 recvfrom() 收到的就是一个完整的报文

  • 报文之间不会混在一起,系统帮你自动分包

  • ⚠ 如果接收方准备的缓冲区(空间)太小,超过部分会直接丢失,不会等下次再接

    例子:

    sendto("hello")  // 发送 5 个字节  
    recvfrom() -> "hell"   // 缓冲区只有 4 个字节,多的 "o" 被丢了
    

2.1.2 字节流传输(TCP)

  • 数据像水流一样传输,没有边界划分

  • send() 发送,用 recv() 接收
    👉 发送多少次不重要,接收方可能一次性收到多个,或者只收到一部分

  • 接收到的数据需要程序自己分辨边界,比如靠分隔符、长度字段等

  • ⚠ 不会丢数据,但会出现“粘包”“拆包”问题

    例子:

    send("hello")  
    send("GuLu")  
    recv() -> "helloGuLu"  // 可能粘在一起  
    recv() -> "hel" + "loGuLu"  // 也可能拆开了
    

2.1.3 总结对比

特点报文传输(UDP)字节流传输(TCP)
是否分包系统自动分包无分包,程序自己判断
接收顺序一次收一个报文一次收若干字节
数据边界天然有边界没有边界(粘包/拆包)
丢数据情况缓冲区小会丢超出部分不会丢,但可能不完整接收
典型函数sendto() / recvfrom()send() / recv()

2.2 TCP 和 UDP 格式对比

在这里插入图片描述

2.3 ARQ协议(Automatic Repeat-reQuest)

ARQ协议(Automatic Repeat-reQuest),即自动重传请求,是传输层的错误纠正协议之一,它通过使用确认和超时两个机制,在不可靠的网络上实现可靠的信息传输。

它的核心机制有两个:

  • 确认(ACK):收到数据后,告诉发送方”我收到了”
  • 超时重传:发送方在规定时间内没收到ACK,就重新发送一次

ARQ的三种常见模式:

  1. 停等式 ARQ(Stop-and-Wait)

    • 每次只发一帧数据,等对方确认(ACK)后才能发下一帧
    • 简单但效率低,容易浪费带宽

    应用:

    • 通常不用于高速网络
    • 类似于 ZeroMQ 的 Request-Respond 模式,一问一答
  2. 回退N帧 ARQ(Go-Back-N)

    • 连续发送多个数据帧,不等ACK,但最多发N个(滑动窗口大小)
    • 如果某一帧出错或丢了,就从那一帧开始全部重传

    特点:

    • 实现简单,效率比停等式高
    • 但会浪费带宽(好的帧也要重发)

    应用:

    • TCP 协议使用了类似机制,但结合了更多优化
  3. 选择性重传 ARQ(Selective Repeat)

    • 连续发送多个帧
    • 如果某一帧丢了,只重传那一帧,不影响其它帧

    特点:

    • 更高效,节省带宽
    • 但实现复杂,需要接收端缓存和编号管理

2.3.1 ARQ协议——停等式(stop-and-wait)

停等协议的工作原理如下:

  1. 发送方对接收方发送数据包,然后等待接收方回复ACK并且开始计时。
  2. 在等待过程中,发送方停止发送新的数据包。
  3. 当数据包没有成功被接收方接收,接收方不会发送ACK。这样发送方在等待一定时间后,重新发送数据包。
  4. 反复以上步骤直到收到从接收方发送的ACK
    在这里插入图片描述缺点:较长的等待时间导致低的数据传输速度。

2.3.2 ARQ协议——回退n帧(go-back-n)

为了克服停等协议长时间等待ACK的缺陷,连续ARQ协议会连续发送一组数据包,然后再等待这些数据包的ACK。

什么是滑动窗口:

  • 发送方和接收方都会维护一个数据帧的序列,这个序列被称作窗口。
  • 发送方的窗口大小由接收方确定,目的在于控制发送速度,以免接收方的缓存不够大,而导致溢出,同时控制流量也可以避免网络拥塞。
  • 协议中规定,对于窗口内未经确认的分组需要重传。

回退N步(Go-Back-N,GBN):

  • 回退N步协议允许发送方在等待超时的间歇,可以继续发送分组。所有发送的分组,都带有序号。

在GBN协议中,发送方需响应以下三种事件:

  1. 上层的调用。上层调用相应send()时,发送方首先要检查发送窗口是否已满。
  2. 接收ACK。在该协议中,对序号为n的分组的确认采取累积确认的方式,表明接收方已正确接收到序号n以前(包括n)的所有分组。
  3. 超时。若出现超时,发送方将重传所有已发出但还未被确认的分组
    在这里插入图片描述
    假如上面 2 这个包丢失了, 3,4,5,6,7,8 都正常发送给对方了,但是如果 2~8 这些包刚好组成一帧数据,那这个时候丢失了 2 这个包,整个数据帧都要进行重传

总结:GBN采用的技术包括序号、累积确认、检验和以及计时/重传

2.3.3 ARQ协议——选择重传(Selective-repeat)

一、基础概念
  • SR协议(选择性重传):只重发丢的那一份,不是全都重发
  • 接收窗口:相当于“我这边正在等哪些包”,假设当前等的是编号 [4, 5, 6, 7]
  • 分组编号:每个数据包都有一个编号,像快递编号一样
  • ACK:收到包之后,回个消息告诉对方“我收到了”
二、接收方需响应的三种事件

假设接收窗口的基序号为4,分组长度也为4,那么接收方处理分组的三种情况(窗口基序号是4)

情况一:收到了当前窗口里正在等的包(编号在 4~7)

就像我在等快递编号 4~7 的包,现在收到了编号是 5 的
  • 我会立刻发一个 ACK(5) 告诉发送方“我收到了包5”
  • 如果这个包我之前还没收到,那我就把它先存起来
  • 如果我现在收到的是编号4,而且之前的 5、6、7 都也到了,那我就可以把这几个包一次性交给上层处理
  • 然后接收窗口就会整体向前滑动,变成等 [8, 9, 10, 11] 的包了

情况二:收到了窗口之前的包(编号是 0~3)

这包我以前收过,现在又来了,但我还是得“礼貌地”回个 ACK
  • 虽然包0~3已经处理过了,但发送方可能没收到我当时的ACK,所以又发了一次
  • 我虽然不处理这个包,但还是要再发一次 ACK
  • 如果我不发ACK,发送方就会以为我没收到,它的窗口就卡在那里不动了

情况三:收到不属于窗口的包(比如编号8、9,但我窗口还在等4~7)

你太着急了,我还没准备好接这个快递,直接无视你。
  • 这些包超前太多了,我现在还没等他们
  • 所以我会直接忽略这个包,不处理也不ACK
三、总结一下行为模式
收到的分组编号处理方式是否ACK
在窗口里(4~7)缓存、发送ACK,必要时上交数据✅ 是
在窗口外但曾收过(0~3)不处理数据,但仍发送ACK✅ 是
超出窗口太多(>7)忽略,不处理也不发ACK❌ 否

![[Pasted image 20250504164439.png]]
假如同样丢失 2 这个包, 3,4,5,6,7,8 都正常发送给对方了,那么我们就只重传 2 这个包即可

2.3.4 总结:三种ARQ对比总结

模式发几帧?出错后怎么办?效率复杂度
停等式 ARQ一次发1帧超时后重发这一帧简单
回退N帧 ARQ连续发N帧出错后,从错帧开始全都重发
选择性重传 ARQ连续发N帧只重发出错的那几帧较复杂

2.4 RTT 和 RTO

RTO(Retransmission Timeout)重传超时时间

  • 定义:发送方等待ACK的最长时间,如果超时还没收到确认,就会重传数据包
  • 作用:防止数据丢失或确认丢失导致的“等不到回复”。

RTT(Round-Trip Time)往返时延

  • 定义:从发送数据到收到确认的总耗时

    • 发送端发出数据
    • 接收端收到后立即发出ACK
    • 发送端收到ACK → 整个过程就是一个 RTT
  • RTT 越大,网络越“慢”;RTT 波动大,表示网络“拥堵”不稳定。

RTT由三部分组成

  1. 传播延迟(Propagation Delay)

    • 信号在电缆/光纤中传输的时间(相对固定)
  2. 处理延迟(Processing Delay)

    • 发送/接收主机处理报文的时间(也比较固定)
  3. 排队延迟(Queuing Delay)

    • 路由器中等待处理的时间(受网络拥塞影响,波动较大

RTO 的设置依赖 RTT 的估计,太短会导致误重传,太长会浪费时间。RTT 是评估网络状态的重要指标,能反映网络是否拥堵。

在这里插入图片描述

2.5 流量控制

双方在通信的时候,发送方的速率与接收方的速率是不一定相等,如果发送方的发送速率太快,会导致接收方处理不过来,这时候接收方只能把处理不过来的数据存在缓存区里(失序的数据包也会被存放在缓存区里) 接收缓存。

如果缓存区满了发送方还在疯狂着发送数据,接收方只能把收到的数据包丢掉,大量的丢包会极大着浪费网络资源,因此,我们需要控制发送方的发送速率, 让接收方与发送方处于一种动态平衡才好。

对发送方发送速率的控制,称之为流量控制。

另外,UDP 要自己控制发送速率,tcp 不用管

一、流量控制——如何控制?

接收方每次收到数据包,可以在发送确定报文的时候,同时告诉发送方自己的缓存区还剩余多少是空闲的,我们也把缓存区的剩余大小称之为接收窗口大小,用变量win来表示接收窗口的大小。

发送方收到之后,便会调整自己的发送速率,也就是调整自己发送窗口的大小,当发送方收到接收窗口的大小为0时,发送方就会停止发送数据,防止出现大量丢包情况的发生。

![[Pasted image 20250504194826.png]]

当发送方停止发送数据后,该怎样才能知道自己可以继续发送数据?

  1. 当接收方处理好数据,接受窗口 win > 0 时,接收方发个通知报文去通知发送方,告诉他可以继续发送数据了。当发送方收到窗口大于0的报文时,就继续发送数据。
  2. 当发送方收到接受窗口 win = 0 时,这时发送方停止发送报文,并且同时开启一个定时器,每隔一段时间就发个测试报文去询问接收方,打听是否可以继续发送数据了,如果可以,接收方就告诉他此时接受窗口的大小;如果接受窗口大小还是为0,则发送方再次刷新启动定时器

在这里插入图片描述

二、流量控制小结

(1) 滑动窗口的基本概念

  • 通信双方都维护两个滑动窗口:

    • 接收窗口:用于接收数据,反映接收方缓存区的可用空间。
    • 发送窗口(拥塞窗口):用于控制发送速率,表示发送方最多能连续发送但未确认的数据量。
  • 接收窗口大小的通知称为“窗口通告”。

(2) 接收窗口大小是否固定?

  • 不是固定的,是根据算法和网络情况动态调整的。丢包多的时候需要减小接收窗口

(3) 接收窗口越大越好吗?

  • 不一定。
    • 当接收窗口超过某个值时,继续增大不能有效减少丢包,反而加剧内存消耗。
    • 所以接收窗口大小应根据网络状况和发送方的拥塞窗口来动态设定。

(4) 接收窗口和发送窗口是否相等?

  • 一般接收窗口 ≥ 发送窗口
    • 接收方在确认报文中会告诉发送方当前的接收窗口大小。
    • 发送方根据这个值来设置自己的发送窗口大小。
    • 但二者并不总是相等,因为接收方发送ACK那一刻,部分数据可能还在处理中。

2.6 拥塞控制

拥塞控制和流量控制虽然采取的动作很相似,但拥塞控制与网络的拥堵情况相关联,而流量控制与接收方的缓存状态相关联
在这里插入图片描述
在这里插入图片描述

2.7 UDP并发编程

在这里插入图片描述
Epoll 如果要同时监听多个端口, 可以考虑使用 epoll方式管理

recvfrom( );

  1. 获取到 udp 数据
  2. 获取到 udp 发送者的 ip + port

三、UDP如何可靠,KCP协议在哪些方面有优势

以10%-20%带宽浪费的代价换取了比 TCP快30%-40%的传输速度。

3.1 UDP 如何实现可靠传输?

UDP 是一种无连接、无状态的传输协议:

  • 不保证数据按顺序到达;
  • 不保证数据一定送达;
  • 不提供重传、流控、拥塞控制。

➤ 所以,为了在 UDP 上实现“可靠”传输,必须在应用层设计一套完整的传输控制机制,包括:

机制描述
序号编号给每个数据包加上序号,接收端可检测出乱序或丢失
ACK(确认机制)接收方对收到的包发确认回执
超时重传(RTO)若某包发送后未在规定时间收到ACK,则重发
滑动窗口控制已发送但未确认的包的数量,实现流控
拥塞控制避免网络过载,比如通过调节发送速率应对丢包
快速重传通过连续的重复ACK判断某个包丢失,提前重传
选择性重传只重传丢失的数据包,而不是后续所有数据

KCP 就是这样一个 基于 UDP 实现可靠传输的协议,其核心机制包括以上全部,并且做了许多优化。

3.2 KCP 协议的核心机制与优化点

KCP 是专为高实时性应用(如游戏、音视频直播)设计的高性能 ARQ(自动重传请求)协议,采用的是 Selective Repeat(选择性重传)方式。其设计目标是:

以一定带宽代价(10%-20%)换取更低延迟和更快传输响应

下面列出 KCP 的主要机制及它相比 TCP 的创新和优化:

1. RTO策略优化(重传超时算法)

  • TCP 的问题:RTO(重传超时时间)在连续丢包时呈指数增长,即 RTO × 2,一旦网络波动严重,会导致超时变得很长(如 100ms → 200ms → 400ms → 800ms)。

  • KCP 的改进

    • 启动“快速模式”后,超时增长为 RTO × 1.5
    • 更快检测超时,更快进行重传;
    • 实验发现 1.5 是一个相对平衡的系数,避免过快过慢。

2. 选择性重传(Selective Retransmission)

  • TCP 的行为:丢了一个包,后面即使收到也不能确认,会一起重传(Go-Back-N 模型的一种变体),浪费带宽。

  • KCP 的行为

    • 只重传确实丢失的包;
    • 接收端告诉发送端哪些包丢了(ACK + UNA 机制);
    • 极大减少不必要的重传,特别适合丢包较多的环境(如无线网络)。

3. 快速重传机制(Fast Retransmit)

  • 当发送方发出 1,2,3,4,5:
    • 如果收到 ACK1、ACK3、ACK4,说明 ACK2 被跳过了。
    • 如果连续被跳过两次(fastresend = 2),认为 2 已丢失,立即重传;
    • 不需要等待 RTO 超时,提高了响应速度。

✅ 这对实时性要求高的场景非常关键。

4. ACK机制(非延迟ACK)

  • TCP 默认采用“延迟ACK”:收数据后不会立即回复ACK,而是等一段时间一起发,提高带宽利用。

    • 问题:超时计算会算出较大 RTT时间,延长了丢包时的判断过程
  • KCP 可调节是否延迟ACK:

    • 默认情况下非延迟;
    • 一收到包就发ACK,加快对丢包的反应速度。

5. ACK + UNA 机制(增强的确认系统)

ARQ模型响应有两种,UNA(此编号前所有包已收到,如TCP)和ACK(该编号包已收到),光用UNA将导致全部重传,光用ACK则丢失成本太高,以往协议都是二选其一, 而 KCP协议中,除去单独的 ACK 包外,所有包都有UNA信息。

  • TCP 仅发送 UNA(Unacknowledged Number Acknowledged),表明“之前的包都收到了”。

    • 缺点:如果只知道某个编号前全部收到,丢了一包就可能触发大范围重传。
  • KCP:ACK + UNA 混合使用

    • 所有数据包中都携带 UNA;
    • 还会显式发送 ACK 指出哪些包已收到;
    • 更加精细化地反馈接收情况,利于实现选择性重传。

6. 流量控制(非退让流控)

KCP正常模式同TCP一样使用公平退让法则,即发送窗口大小由:发送缓存大小、接收端剩余接收缓存大小、丢包退让及慢启动这四要素决定。但传送及时性要求很高的小数据时,可选择通过配置跳过后两步,仅用前两项来控制发送频率。以牺牲部分公平性及带宽利用率之代价,换取了开着BT都能流畅传输的效果。

  • TCP 使用“公平退让”:慢启动 + 拥塞控制,避免网络拥塞。

  • KCP 在默认模式下也模仿 TCP,但:

    • 可配置为“非退让模式”:
      • 不慢启动、不退让;
      • 仅受发送缓存和接收缓存限制;
      • 在网络被其他任务抢占时也能保证 KCP 流畅(如:BT 下载时直播不卡)。

✅ 实时性优先级高的应用,使用非退让可大幅改善体验。

3.3 KCP 相比 TCP 的优势与劣势

项目TCPKCP
协议层级内核协议栈,系统级别应用层,可嵌入程序自由定制
可靠性机制强,但机制较老同样可靠,机制灵活且优化
流控和拥塞控制慢启动,指数回退可配置跳过慢启动,适用于高实时性
丢包处理整体重传效率低快速+选择性重传,效率高
响应时延ACK/重传反应较慢响应更快(RTO更低、ACK非延迟)
带宽利用高,适合大文件、稳定网络带宽略低,适合高抖动网络
部署难度操作系统内置,无需部署需集成到应用层,自行处理逻辑

3.4 KCP 适合哪些应用场景?

场景说明
实时游戏网络要求延迟低,KCP表现优越
音视频直播一边上传,一边播放,要求传输稳定迅速
移动端应用网络质量不稳定,KCP比TCP表现更好
实验性网络协议开发自定义可靠传输策略,KCP高度灵活
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值