UDP与KCP详解
UDP
以及TCP是什么。我们知道传输层中有TCP和UDP两种网络协议,这节就讲UDP是什么。
Internet协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol)。UDP为应用程序提供了一种无需建立连接就可以发送封装的IP数据包的方法。RFC 768描述了UDP。
UDP API
图片来自网络

TCP与UDP的不同
UDP和TCP协议的主要区别是两者在如何实现信息的可靠传递方面不同。TCP协议中包含了专门的传递保证机制,当数据接收方收到发送方传来的信息时,会自动向发送方发出确认消息;发送方只有在接收到该确认消息之后才继续传送其它信息,否则将一直等待直到收到确认信息为止。与TCP不同,UDP协议并不提供数据传送的保证机制。如果在从发送方到接收方的传递过程中出现数据包的丢失,协议本身并不能做出任何检测或提示。因此,通常人们把UDP协议称为不可靠的传输协议。
- TCP是面向连接的传输控制协议,而UDP提供了无连接的数据报服务;
- TCP 具有高可靠性,确保传输数据的正确性,不出现丢失或乱序;UDP 在传输数据前不建立连接,不对数据报进行检查与修改,无须等待对方的应答,所以会出现分组丢失、重复、乱序,应用程序需要负责传输可靠性方面的所有工作;
- UDP具有较好的实时性,工作效率较TCP协议高;
- UDP段结构比 TCP的段结构简单,因此网络开销也小。
- TCP协议可以保证接收端毫无差错地接收到发送端发出的字节流,为应用程序提供可靠的通信服务。对可靠性要求高的通信系统往往使用TCP传输数据。
KCP
什么是KCP
TCP优缺点:
我们知道TCP有超时重传和滑动窗口机制提供了TCP的可靠性和流控特性,滑动窗口和拥塞控制可以使得TCP做到流量控制。但是TCP协议是从大局上考虑的,大公无私,经常牺牲自己速度来减少网络拥塞。且TCP高度自治,很多参数没法配置。
UDP优缺点:
UDP协议简单,所以它更快。但是,UDP毕竟是不可靠的,应用层收到的数据可能是缺失、乱序的。
不管是端游还是手游,对于延时的要求都同样重要,因为延时直接关系到游戏的体验。并且不同的游戏对延时的忍受程度不尽相同,例如:FPS延时超过了100ms体验就不怎么好了,Moba在这种程度却觉得很好,MMO甚至到了200ms还可以愉快玩耍,但不管什么游戏,延时越低,体验就越好。
TCP的特性导致网络在不好的时候,延迟会变的很高。UDP的延迟很低,但是不可靠,乱序。
KCP是一种网络传输协议(A Fast and Reliable ARQ Protocol),纯算法实现,并不负责底层协议(如UDP)的收发,需要使用者自己定义下层数据包的发送方式,以callback的方式提供给KCP。连时钟都需要外部传递进来,内部不会有任何一次系统调用。本文传输协议只考虑UDP的情况。
KCP基于UDP协议,在尽可能保留UDP快的前提下,借鉴了TCP的机制来保证可靠。KCP相比TCP浪费了10%~20%的带宽代价,换取了平均延迟降低30%~40%,且最大延迟降低三倍的传输效果。
KCP是自私的,它只顾自己的传输效率,从不管整个网络的拥塞情况。举个例子,TCP检测到丢包的时候,首先想到的是网络拥塞了,要放慢自己的速度别让网络更糟,而KCP想到的赶紧重传别耽误事。
对比KCP和TCP:
- KCP尽可能保留UDP快的特点下,保证可靠;TCP保证网络绝对的可靠,所以设计复杂,速度慢。
- KCP是为流速设计的,重点是降低应用网络延迟;TCP是为流量设计的,可以充分利用带宽。
- KCP是应用层协议,底层是UDP;TCP是传输层协议。
用个比喻来形容就是TCP是条流速较慢但是流量很大的运河,而KCP是条水流湍急的小激流。
KCP协议只有 ikcp.h, ikcp.c两个源文件,可以方便的集成到用户自己的协议栈中。
图片来自网络:

KCP工作流程
KCP的工作流程如下图所示:


图中的send_queue是发送队列,send_buf是发送缓冲区,rcv_buf是接收缓冲区,rcv_queue是接收队列。队列和缓冲区的实现都是双向循环列表,通过宏定义来实现。queue和buff的结点就是一个kcp报文。
- ikcp_update:循环定时调用
发送工作流程:
- ikcp_send: 将用户待发送的数据填充成KCP报文段,放入snd_queue。
- ikcp_flush: 调用输出回调将发送缓冲区中的数据发送出去。Ikcp_send不会将数据直接发送出去,只会将报文段放入snd_queue,等待下一次ikcp_update来调用ikcp_flush,将数据从snd_queue中移动到snd_buf后再发送数据。具体哪些报文可以发送,需要通过滑动窗口来控制,避免一次性发送太多的数据导致拥塞。
通过发送工作流程,可以发现发送数据需要等待flush,有发送延迟问题。普遍的解决方案是send之后立即调用一次update,但这样做会带来较大的系统开销。
接收工作流程:
- ikcp_input: 接收传输层数据,包括用户数据报文段以及ACK报文;接收完后放入rcv_buff,等到接收完一段完整有序的报文之后,才会移动到rcv_queue中供接收方处理。
- ikcp_recv:从rcv_queue中读取数据,触发接收逻辑。
可靠性
ARQ协议(Automatic Repeat-reQuest),即自动重传请求,是传输层的错误纠正协议之一,它通过使用确认和超时两个机制,在不可靠的网络上实现可靠的信息传输。TCP就是使用的ARQ协议来保证了数据的可靠。
ARQ协议有两种模式:
- ACK模式(停等ARQ协议),同步请求响应模式,基于超时重传保证可靠。
- UNA模式(连续ARQ协议),可以连续发送多个分组,而不必每发完一个分组就停下来等待对方确认,TCP就是如此。连续ARQ协议不会响应每个数据段,而是仅仅响应编号最大的这个数据段,表示之前的数据都收到了。
KCP的ARQ:光用UNA如果丢包将导致全部重传,光用ACK则丢失成本太高。以往协议都是二选其一,而KCP有单独ACK包,且数据包和ACK包都带UNA信息,有效降低ACK丢失成本。
确认与重传
KCP 确认重传实现机制:ACK+UNA;超时重传+快速重传;选择重传
- 在TCP中,有超时重传机制,KCP中设置快速模式,可控制RTO成*1.5。
- 由于KCP的ARQ模式是ACK+UNA,所以KCP除了超时重传还有选择重传机制
- 选择重传:返回的ACK中包含rcv_nxt和sn。rcv_nxt代表收到的所有连续的包,sn代表哪些不连续的包收到了,那么根据这两个参数可以计算出来没有收到的包的序号。发送方接收到接收方发过来的数据时,首先解析rcv_nxt,把所有小于rcv_nxt序号的包从发送缓存队列中移除。然后再解析sn(大于rcv_nxt),遍历发送缓存队列,找到所有序号小于sn的包,就是被选择重传的包。
- 快速重传:根据我们设置的快速重传的门限,对每个分片维护一个快速重传的计数。每收到一个ACK解析sn后找到了一个分片,就把该分片的快速重传的计数加一。如果该计数达到了快速重传门限,那么就认为该分片已经丢失,可以触发快速重传。
- KCP在发生快速重传且数据包乱序时,采用的是TCP快恢复的策略。控制窗口调整为已经发送没有接收到ack的数据包数目的一半+resent。
流量控制
流量控制有两机制:滑动窗口和拥塞控制。
滑动窗口的接收方告知发送方自己可以接收缓冲区的大小,通常与连续ARQ协议配合使用。滑动窗口就是TCP头部的16位大小窗口字段,而UDP没有这个字段。
拥塞控制的关键是四个算法:慢开始、拥塞避免、快速重传、快速恢复。
KCP滑动窗口:
滑动窗口默认大小为32,即可以接收最大为32*MTU=43.75kB。KCP采用update的方式,更新间隔为10ms,那么KCP限定了你最大传输速率为4375kB/s,在高网速传输大内容的情况下需要调用ikcp_wndsize调整接收与发送窗口。建议从应用侧更好的控制发送流量与网络速度持平,避免缓存堆积延迟。
KCP拥塞控制:
KCP的拥塞控制可以关闭。KCP的优势在于可以完全关闭拥塞控制,非常自私的进行发送。KCP采用的拥塞控制策略为TCP最古老的策略,无任何优势。完全关闭拥塞控制,也不是一个最优策略,它全是会造成更为拥堵的情况。
KCP VS TCP
- TCP的RTO是直接翻倍,但是试验测试发现RTO*=1.5比RTO*=2要好,所以KCP选择了RTO*=1.5,提高了丢包时的传输速度。
- 快速重传:发送端发送了1,2,3,4,5几个包,然后收到远端的ACK: 1, 3, 4, 5,当收到ACK3时,KCP知道2被跳过1次,收到ACK4时,知道2被跳过了2次,此时可以认为2号丢失,不用等超时,直接重传2号包,大大改善了丢包时的传输速度。
- 延迟ACK vs 非延迟ACK :TCP为了充分利用带宽,延迟发送ACK(NODELAY都没用),这样超时计算会算出较大RTT时间,延长了丢包时的判断过程。KCP的ACK是否延迟发送可以调节。
- UNA vs ACK+UNA :TCP使用的UNA模式,有丢包全部重传问题;KCP有单独ACK,且数据包和ACK包都带UNA信息,有效降低ACK丢失成本。
- TCP丢包时会全部重传从丢的那个包开始以后的数据;由于KCP使用了ACK+UNA模式,KCP是选择性重传,只重传真正丢失的数据包。
- 非退让流控:KCP正常模式同TCP一样使用公平退让法则,即发送窗口大小由:发送缓存大小、接收端剩余接收缓存大小、丢包退让及慢启动这四要素决定。但传送及时性要求很高的小数据时,可选择通过配置跳过后两步,仅用前两项来控制发送频率。以牺牲部分公平性及带宽利用率之代价,换取了开着BT都能流畅传输的效果。(KCP非退让流控可以理解为对及时性要求很高的小数据只考虑滑动窗口,看你发送窗口和接收窗口是否允许我传输)
其他
- 当用户数据很大,大于一个UDP包能承担的范围时(大于mss),KCP会将用户数据分片存储在多个KCP包中。因此每个KCP包称为一个分片。
- 用户控制:拥塞控制可以取消、ACK回复可以设置成无延迟ACK回复、KCP的RTO可以控制成*1.5
- KCP只是一套基于无连接的数据报文之上的连接和拥塞控制协议,对底层无连接的数据报文没有具体的限制,可以基于UDP,也可以基于伪造的 TCP/ICMP等,也可以基于某些特殊环境的非internet网络(比如各种现场通信总线)
UDP与KCP详解的更多相关文章
- 以太网帧格式、IP数据报格式、TCP段格式+UDP段格式 详解
转载:http://www.cnblogs.com/lifan3a/articles/6649970.html 以太网帧格式.IP数据报格式.TCP段格式+UDP段格式 详解 1.ISO开放系统有 ...
- 计算机网络(六),UDP报文段详解
目录 1.UDP作用 2.UDP报文段详解 六.UDP报文段详解 1.UDP作用 (1)面向非连接 (2)不维护连接状态,支持同时向多个客户端传送相同的消息 (3)报文段报头只有8个字节,格外开销较小 ...
- TCP、UDP和HTTP详解
http:是用于www浏览的一个协议.tcp:是机器之间建立连接用的到的一个协议. 1.TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层.在网络层有IP协议.ICMP协议.ARP协议.R ...
- 网络编程UDP、TCP详解
网络编程 网络编程主要用于解决计算机与计算机(手机.平板-)之间的数据传输问题. 1.InetAddress(IP类) 方法: 方法 描述 getLocalHost() 获取本机的IP地址对象 ...
- 《TCP/IP详解卷1:协议》第11章 UDP:用户数据报协议-读书笔记
章节回顾: <TCP/IP详解卷1:协议>第1章 概述-读书笔记 <TCP/IP详解卷1:协议>第2章 链路层-读书笔记 <TCP/IP详解卷1:协议>第3章 IP ...
- TCP/UDP详解
转载:http://www.cnblogs.com/visily/archive/2013/03/15/2961190.html, 作者:望梅止渴 相关: HTTP协议详解 深入理解HTTP协议 T ...
- ip头、tcp头、udp头详解及定义,结合Wireshark抓包看实际情况
公司的同事们在分析网页加载慢的问题,忽然使用到了Wireshark工具,我就像发现新大陆一样好奇,赶紧看了看,顺便复习了一下相关协议.上学时学的忘的差不多了,汗颜啊! 报文封装整体结构 mac帧头定义 ...
- TCP/IP、UDP、HTTP、SOCKET详解
文章大纲 网络OSI七层及各层作用 TCP与UDP基本介绍 TCP连接过程详解 SOCKET原理与连接详解 一.网络OSI七层及各层作用 应用层:文件传输,电子邮件,文件服务,虚拟终端 T ...
- TCP、UDP详解与抓包工具使用
参考:https://www.cnblogs.com/HPAHPA/p/7737641.html TCP.UDP详解 1.传输层存在的必要性 由于网络层的分组传输是不可靠的,无法了解数据到达终点的时间 ...
- 【TCP/IP详解 卷一:协议】第十一章 UDP 用户数据报协议
11.1 引言 UDP 是一个简单的 面向数据报 的运输层协议:进程的每个 输出操作 都正好产生一个 UDP数据报,并且组装成一份待发送的IP数据报. 这与 TCP 不一样,它是 面向流字符 的协议, ...
随机推荐
- 流水线中便捷迭代,鲲鹏DevKit 23.0新能力抢先看
本文分享自华为云社区<鲲鹏DevKit 23.0:流水线中便捷迭代鲲鹏版本,迁移.开发.调优无缝衔接>,作者:华为云社区精选 . 数字时代,海量的行业应用驱动着多样性算力的飞速发展,以鲲鹏 ...
- 【京东开源项目】微前端框架MicroApp 1.0正式发布
介绍 MicroApp是由京东前端团队推出的一款微前端框架,它从组件化的思维,基于类WebComponent进行微前端的渲染,旨在降低上手难度.提升工作效率.MicroApp无关技术栈,也不和业务绑定 ...
- docker入门加实战—项目部署之DockrCompose
docker入门加实战-项目部署之DockrCompose 我们部署一个简单的java项目,可能就包含3个容器: MySQL Nginx Java项目 而稍微复杂的项目,其中还会有各种各样的其它中间件 ...
- 用ps命令查看进程的内存
http://blog.csdn.net/tigerscorpio/article/details/5960705 http://blog.csdn.net/licanhua/article/deta ...
- 整理unity资料
https://www.cnblogs.com/fly-100/p/3910515.html 协同的概念介绍
- ReverseMe-120
一道好题,没解出来但是收获很多 贴两位大牛的题解 [精选]攻防世界逆向高手题之ReverseMe-120-CSDN博客 攻防世界ReverseMe-120详解_攻防世界reverseme基本思路-CS ...
- 01_实验一_操作系统的启动start
实验一 操作系统的启动 从源代码到可运行的操作系统(前置知识) API 与 SDK 以 C 语言编写的操作系统为背景进行介绍,EOS 是由 C 语言编写的 操作系统和应用程序之间一个重要的纽带就是应用 ...
- 计算网络之MSTP协议与VRRP协议
一.MSTP协议 MSTP协议出现是基于STP协议和RSTP协议的,要了解MSTP协议就需要先了解其它两个协议 首先,STP协议是交换机生成树协议,它的出现主要是为了解决二层交换机环路的问题,当多个交 ...
- 16个值得推荐的.NET ORM框架(含使用情况统计的投票,欢迎参与)
什么是ORM? ORM 是 Object Relational Mapping 的缩写,译为"对象关系映射",是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的 ...
- 大白话说Python+Flask入门(二)
写在前面 笔者技术真的很一般,也许只靠着笨鸟先飞的这种傻瓜坚持,才能在互联网行业侥幸的生存下来吧! 为什么这么说? 我曾不止一次在某群,看到说我写的东西一点技术含量都没有,而且很没营养,换作一年前的我 ...