一、UDP协议

UDP用户数据报协议,非连接的协议,传输数据之前源端和终端不建立连接,当它想传送时直接去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。

UDP传输协议的特点

  • UDP无连接,时间上不存在建立连接需要的时延。
  • UDP没有拥塞控制,应用层能够更好的控制要发送的数据和发送时间,网络中的拥塞控制也不会影响主机的发送速率。
  • UDP提供尽最大努力的交付,不保证可靠交付。所有维护传输可靠性的工作需要用户在应用层来完成。
  • UDP是面向报文的,对应用层交下来的报文,添加首部后直接向下交付给IP层,既不合并,也不拆分,保留这些报文的边界。
  • UDP常用一次性传输比较少量数据的网络应用,如DNS,SNMP等;

UDP的首部格式

UDP校验

计算校验和的时候,需要在UDP数据报之前增加12字节的伪首部,伪首部并不是UDP真正的首部。 仅仅是为了计算校验和。这样的校验和,既检查了UDP数据报,又对IP数据报的源IP地址和目的IP地址进行了检验。

UDP客户端和服务器端编程示例

客户端:

#include<sys/socket.h>
#include<stdio.h>
#include<assert.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<string.h>
#include<unistd.h>
int main()
{//创建套接字,SOCK_DGRAM为UDP数据报套接字int fd=socket(AF_INET,SOCK_DGRAM,0);assert(fd!=-1);struct sockaddr_in saddr;//服务器套接字结构struct sockaddr_in caddr;//客户端套接字结构//saddr其实有四项成员,最后一项用来占位的,必须搞为0,索性我们开始直接给全部置为0,后面再来绑定ip和端口saddr.sin_family=AF_INET;//地址族,TCP/ipv4协议族saddr.sin_port=htons(6000);//将端口值从小端序列转换为大端序列saddr.sin_addr.s_addr=inet_addr("172.27.209.173");//将一个点分十进制的ip地址转换为一个长整型数while(1){//创建发送缓冲区char buff[128]={0};//从标准输入中输入数据fgets(buff,128,stdin);//设置退出暗号if(strncmp(buff,"break",5)==0)break;//向服务器发送数据sendto(fd,buff,sizeof(buff)-1,0,(struct sockaddr*)&saddr,sizeof(saddr));//将发送缓冲区转换成接收缓冲区memset(buff,0,128);int len = sizeof(saddr);//接收服务器的数据回复recvfrom(fd,buff,127,0,(struct sockaddr*)&saddr,(socklen_t*)&len);printf("buff: %s \n",buff);}close(fd);
}

服务器端:

#include<sys/socket.h>
#include<stdio.h>
#include<assert.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
int main()
{//创建套接字,SOCK_DGRAM为UDP数据报套接字int fd=socket(AF_INET,SOCK_DGRAM,0);assert(fd!=-1);struct sockaddr_in saddr;//服务器套接字结构struct sockaddr_in caddr;//客户端套接字结构//saddr其实有四项成员,最后一项用来占位的,必须搞为0,索性我们开始直接给全部置为0,后面再来绑定ip和端口saddr.sin_family=AF_INET;//地址族,TCP/ipv4协议族saddr.sin_port=htons(6000);//将端口值从小端序列转换为大端序列saddr.sin_addr.s_addr=inet_addr("172.27.209.173");//将一个点分十进制的ip地址转换为一个长整型数//将套接字fd与本地ip地址绑定【此处注意强转】int res=bind(fd,(struct sockaddr*)&saddr,sizeof(saddr));assert(res!=-1);/*UDP协议传输中没有监听队列这个东西*/while(1){//接收缓冲区char buff[128]={0};int len=sizeof(caddr);//接收来自客户端发送的数据recvfrom(fd,buff,127,0,(struct sockaddr*)&caddr,(socklen_t*)&len);printf("buff: %s\n",buff);//将OK发送回客户端sendto(fd,"ok\n",3,0,(struct sockaddr*)&caddr,(socklen_t)len);}close(fd);
}

二、QUIC协议

1.QUIC 是如何实现可靠传输的?

一个 Packet 报文中可以存放多个 QUIC Frame。每一个 Frame 都有明确的类型,针对类型的不同,功能也不同,自然格式也不同。

举例 Stream 类型的 Frame 格式,Stream 可以认为就是一条 HTTP 请求:

  • Stream ID 作用:多个并发传输的 HTTP 消息,通过不同的 Stream ID 加以区别,类似于 HTTP2 的 Stream ID;
  • Offset 作用:类似于 TCP 协议中的 Seq 序号,保证数据的顺序性和可靠性
  • Length 作用:指明了 Frame 数据的长度。

数据包 Packet N 丢失了,后面重传该数据包的编号为 Packet N+2,丢失的数据包和重传的数据包 Stream ID 与 Offset 都一致,说明这两个数据包的内容一致。这些数据包传输到接收端后,接收端能根据 Stream ID 与 Offset 字段信息将 Stream x 和 Stream x+y 按照顺序组织起来,然后交给应用程序处理。

总的来说,QUIC 通过单向递增的 Packet Number,配合 Stream ID 与 Offset 字段信息,可以支持乱序确认而不影响数据包的正确组装,摆脱了TCP 必须按顺序确认应答 ACK 的限制,解决了 TCP 因某个数据包重传而阻塞后续所有待发送数据包的问题。

2.QUIC 是如何解决 TCP 队头阻塞问题的?

HTTP/2 的队头阻塞

HTTP/2 多个 Stream 请求都是在一条 TCP 连接上传输,这意味着多个 Stream 共用同一个 TCP 滑动窗口,那么当发生数据丢失,滑动窗口是无法往前移动的,此时就会阻塞住所有的 HTTP 请求,这属于 TCP 层队头阻塞。

没有队头阻塞的 QUIC

QUIC 给每一个 Stream 都分配了一个独立的滑动窗口,这样使得一个连接上的多个 Stream 之间没有依赖关系,都是相互独立的各自控制的滑动窗口

假如 Stream2 丢了一个 UDP 包,也只会影响 Stream2 的处理,不会影响其他 Stream,与 HTTP/2 不同,HTTP/2 只要某个流中的数据包丢失了,同一个HTTP连接的其他流也会因此受影响。

3.QUIC 是如何做流量控制的?

同一个 Stream 的数据也是要保证顺序的,不然无法实现可靠传输,因此同一个 Stream 的数据包丢失了,也会造成窗口无法滑动

QUIC 的 每个 Stream 都有各自的滑动窗口,不同 Stream 互相独立,队头的 Stream A 被阻塞后,不妨碍 StreamB、C的读取。而对于 HTTP/2 而言,所有的 Stream 都跑在一条 TCP 连接上,而这些 Stream 共享一个滑动窗口,因此同一个连接内,Stream A 被阻塞后, StreamB、StreamC 必须等待。

QUIC 实现了两种级别的流量控制,分别为 Stream 和 Connection 两种级别:

  • Stream 级别的流量控制:Stream 可以认为就是一条 HTTP 请求,每个 Stream 都有独立的滑动窗口,所以每个 Stream 都可以做流量控制,防止单个 Stream 消耗连接的全部接收缓冲。
  • Connection 级别的流量控制:限制连接中所有 Stream 相加起来的总字节数,防止发送方超过连接的缓冲容量。

Stream 级别的流量控制:

Connection 级别的流量控制

4.QUIC 对拥塞控制改进

因为 QUIC 处于应用层,所以就可以针对不同的应用设置不同的拥塞控制算法。

5.QUIC 更快的连接建立

QUIC 内部包含了 TLS,它在自己的帧会携带 TLS 里的“记录”,再加上 QUIC 使用的是 TLS1.3,因此仅需 1 个 RTT 就可以「同时」完成建立连接与密钥协商,甚至在第二次连接的时候,应用数据包可以和 QUIC 握手信息一起发送,达到 0-RTT 的效果。

QUIC 具体握手过程如下:

  1. 客户端判断本地是否已有服务器的全部配置参数(证书配置信息),如果有则直接跳转到(5),否则继续;
  2. 客户端向服务器发送CHLO消息,请求服务器传输配置参数;
  3. 服务器收到 CHLO,回复REJ消息,其中包含服务器的部分配置参数;
  4. 客户端收到REJ,提取并存储服务器配置参数,跳回到(1) ;
  5. 客户端向服务器发送 full client hello 消息,开始正式握手,消息中包括客户端选择的一个公开数。此时客户端根据获取的服务器配置参数客户端选择的公开数,可以计算出初始密钥 K1
  6. 服务器收到 full client hello,如果同意连接,根据客户端的公开数计算出初始密钥 K1,回复 SHLO消息,SHLO 用初始密钥 K1 加密,并且其中包含服务器选择的一个临时公开数
  7. 客户端收到服务器的回复,如果是 SHLO,则尝试用初始密钥 K1 解密,提取出临时公开数
  8. 客户端和服务器根据临时公开数和初始密钥 K1,各自基于 SHA-256 算法推导出会话密钥 K2;
  9. 双方更换为使用会话密钥 K2 通信,初始密钥 K1 此时已无用,QUIC 握手过程完毕。

上述QUIC握手步骤,其中步骤1-4均为客户端获取服务器配置信息步骤5-8为真正的握手阶段耗时1RTT

6.QUIC 是如何迁移连接的?

那么当移动设备的网络从 4G 切换到 WIFI 时,意味着 IP 地址变化了,那么就必须要断开连接,然后重新建立 TCP 连接

而建立连接的过程包含 TCP 三次握手和 TLS 四次握手的时延,以及 TCP 慢启动的减速过程,给用户的感觉就是网络突然卡顿了一下,因此连接的迁移成本是很高的。

QUIC 协议没有用四元组的方式来“绑定”连接,而是通过64 位的随机数作为连接 ID来标记通信的两个端点,客户端和服务器可以各自选择一组 ID 来标记自己,因此即使移动设备的网络变化后,导致 IP 地址变化了,只要仍保有上下文信息(比如连接 ID、TLS 密钥等),就可以“无缝”地复用原连接,消除重连的成本,没有丝毫卡顿感,达到了连接迁移的功能。

UDP通信协议详解_udp_神厨小福贵!-DevPress官方社区
4.17 如何基于 UDP 协议实现可靠传输? | 小林coding
QUIC 协议原理浅解_腾讯技术工程的博客-CSDN博客
HTTP/3核心概念之QUIC - 掘金
10 分钟讲完 QUIC 协议 - 掘金

基于UDP的可靠传输——QUIC 协议相关推荐

  1. UDT:基于UDP的可靠传输协议

    基于UDP 上的UDT ,比TCP传输效率高 UDT:基于UDP的数据传输协议(初译) (译者:Jack) Status of this Memo This Internet-Draft is sub ...

  2. QUIC之UDP实现可靠传输

    QUIC简介 QUIC的全称是 Quick UDP Internet Connection,叫做快速UDP网络连接,是Google提出的一个基于UDP的可靠的安全的传输协议. QUIC的改进 相较于H ...

  3. 支付宝二面:如何用 UDP 实现可靠传输?

    相信大家面试经常会被问到一个问题 "如何用UDP实现可靠传输",今天就给大家分享一个基于 UDP 实现的可靠传输协议:QUIC . 这几天看到一篇蚂蚁集团实战 QUIC 的文章,我 ...

  4. TCP 是一个可靠传输的协议,那我们来重点介绍 TCP 的重传机制、滑动窗口、流量控制、拥塞控制。

    TCP 巨复杂,它为了保证可靠性,用了巨多的机制来保证,真是个「伟大」的协议,写着写着发现这水太深了... 本文的全部图片都是小林绘画的,非常的辛苦且累,不废话了,直接进入正文,Go! 相信大家都知道 ...

  5. 用udp实现可靠传输python_一种基于UDP协议实时可靠图像传输方案的制作方法

    本发明设计属于数据传输与通信技术领域,具体涉及一种基于UDP协议(User Datagram Protocol)实时可靠图像传输方案. 背景技术: 随着网络技术的高速发展,无线数据传输在通信.控制等领 ...

  6. kcp 协议分析 基于udp的可靠协议

    项目地址:https://github.com/skywind3000/kcp 此项目是基于c语言的 其他语言实现自行搜索 简介 KCP是一个快速可靠协议,能以比 TCP浪费10%-20%的带宽的代价 ...

  7. UDT协议-基于UDP的可靠数据传输协议

    1.   介绍 随着网络带宽时延产品(BDP)的增加,通常的TCP协议开始变的低效.这是因为它的AIMD(additive increase multiplicative decrease)算法彻底减 ...

  8. 如何利用UDP实现可靠传输(RUDP)

    4.UDP的三角制约原则 其实在实时通信领域存在一个三角平衡关系--成本.质量和时延三者的制约关系: 也就是说投入的成本.获得的质量和通信的时延之间是一个三角制约 (LEQ) 关系,所以实时通信系统的 ...

  9. DHCP:实现基于UDP的主机动态配置协议

    主机动态配置协议是在无线互联时代,我们"日用而不知"的幕后英雄.试想你拿着手机,连接上wifi后就可以上网,如果没有改协议的存在,我们估计没有那么轻松自如就能惬意的在指尖冲浪. 该 ...

最新文章

  1. Linux VIM IDE
  2. Windows 7 shortcut icons missing (快捷方式图标丢失)
  3. 第六章 SpringCloud之Ribbon负载均衡
  4. React组件方法中为什么要绑定this
  5. linux网卡握手速率模式,一种基于Linux平台下的网卡速率和双工模式测试的方法与流程...
  6. Linux平台Segmentation fault(段错误)调试方法
  7. JAVA日期时间相关库
  8. BZOJ 1606: [Usaco2008 Dec]Hay For Sale 购买干草(动态规划)
  9. 时间操作(JavaScript版)—页面显示格式:年月日 时分秒 星期
  10. 程序员必须掌握的十大经典算法
  11. 在Vue项目中引入 ECharts 3D 路径图 Flights GL(需安装echarts、echarts-gl、jQuery依赖,已踩坑)
  12. 绘图工具 Gliffy 使用简介
  13. 使用PHP连接MySQL数据库的代码
  14. 视频教程-思科CCNP专题系列②:EIGRP路由协议-思科认证
  15. 从远景论坛上学到的完美激活NERO8 NERO9的经验
  16. Mysql将分组后产生的同一分组的值连接起来
  17. fluent周期边界_在Fluent中采用TUI设置周期性边界的方法
  18. 中南大学复试上机:1009: 安全路径
  19. 树的先序/中序/后序遍历
  20. JS身份证号码校验,JS根据身份证号码获取出生年月日,JS根据出生年月日获取年龄,JS根据身份证号码获取性别

热门文章

  1. 投资高手三十年投资经验总结的18条真谛
  2. groovy-时间转换
  3. WAIC 2020 微软论坛精彩全回顾!
  4. Vue-elementui-admin 快捷标签导航栏解决切换路由不刷新问题
  5. 反证法在计算机领域,人工智能的基础研究领域——问题求解、逻辑推理与定理证明...
  6. 电脑游戏怎么转移新电脑,换新电脑如何迁移游戏
  7. 电脑重装系统之后风扇一直很响如何优化
  8. 2021云计算技能竞赛真题
  9. synergy软件win10和ubuntu16.04局域网下使用一套键盘鼠标系统
  10. 利用keytool工具生成数字证书