惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
S
Securelist
V
Vulnerabilities – Threatpost
C
Cyber Attacks, Cyber Crime and Cyber Security
Schneier on Security
Schneier on Security
Cyberwarzone
Cyberwarzone
Simon Willison's Weblog
Simon Willison's Weblog
Hacker News - Newest:
Hacker News - Newest: "LLM"
P
Palo Alto Networks Blog
T
Troy Hunt's Blog
SecWiki News
SecWiki News
Security Archives - TechRepublic
Security Archives - TechRepublic
T
The Blog of Author Tim Ferriss
Project Zero
Project Zero
Microsoft Security Blog
Microsoft Security Blog
The Register - Security
The Register - Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
J
Java Code Geeks
F
Full Disclosure
阮一峰的网络日志
阮一峰的网络日志
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Attack and Defense Labs
Attack and Defense Labs
Know Your Adversary
Know Your Adversary
WordPress大学
WordPress大学
PCI Perspectives
PCI Perspectives
N
News | PayPal Newsroom
The Last Watchdog
The Last Watchdog
酷 壳 – CoolShell
酷 壳 – CoolShell
P
Privacy & Cybersecurity Law Blog
P
Proofpoint News Feed
V
Visual Studio Blog
C
CERT Recently Published Vulnerability Notes
H
Help Net Security
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
云风的 BLOG
云风的 BLOG
月光博客
月光博客
T
The Exploit Database - CXSecurity.com
I
InfoQ
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
U
Unit 42
腾讯CDC
小众软件
小众软件
V2EX - 技术
V2EX - 技术
罗磊的独立博客
Cloudbric
Cloudbric
Recorded Future
Recorded Future
IT之家
IT之家
Google DeepMind News
Google DeepMind News
C
CXSECURITY Database RSS Feed - CXSecurity.com

程序员笔记(huoyijie.cn)

generate new dataset with llm and knowledge graph resume deepseek applications Implement the classic huarongdao game with react Implement the classic tetris game with react Writing admin dashboard template with Nextjs How to AuthN user with OpenLDAP share whiteboard with websocket ocr overview tech notes subscribe topic with sse multi devices github an algorithm used for image text detect an algorithm used for image text detect facial expression recognition technology based on neural network oauth2 mysql store a real time collaborative whiteboard with infinite space How to perform load testing with Grafana k6 fix split of undefined with gitbook theme nodejs http proxy middleware analyze referer of express website writing a CDN origin server with Django a personal lightweight CMS tool writing in Golang profile introduce the post processing introduce the text detect method blockchain for dummies medical applications on ai facial expression recognition study facial expression recognition auth auth with oauth2 auth with jwt chat with sse react chat with websocket react http message signatures infinite whiteboard with socket.io multi factor auth with totp subscribe topic with sse capture screen to gif Golang 经典入门实践教程 · GitBook EFS 加密文件系统 · GitBook 弈杰围棋智能终端 · GitBook 如何把手机触摸屏变成触控板(Touchpad) · GitBook 基于 SOCKET.IO 搭建个人电脑 HTTP 静态服务器代理 · GitBook 三百行代码搭建一个简单的 SOCKS5 代理服务器 · GitBook 微信小程序(蓝牙BLE)远程遥控树莓派小车 · GitBook 语音远程遥控树莓派小车 · GitBook 树莓派的一些使用经验 · GitBook 从零开始制作树莓派小车 · GitBook UDPack 2.0 协议 · GitBook 升级 Ubuntu 到 20.04 LTS 长期维护版本 · GitBook 反向代理服务器实现原理 · GitBook 网站支持 HTTP 2.0 · GitBook 搭建配置邮件服务器 · GitBook 使用 Git 与 Gitbook 创建管理电子书 · GitBook 网站图片视频接入CDN · GitBook a personal lightweight self hosted git server written in Golang 快速搭建CDN回源服务器 · GitBook 基于 Git 搭建代码托管服务器 · GitBook
前言 · GitBook
huoyijie · 2024-05-24 · via 程序员笔记(huoyijie.cn)

基于 UDP 的安全可靠数据包传输协议(UDPack)

前言

众所周知,UDP 协议简单,报文收发速度快。但是 UDP 协议本身是不可靠的,数据报文在路由过程中可能会被丢弃。由于互联网拓扑结构的复杂性和动态性,连续发送的数据报文,路由也会不同,由于中间节点的处理延时,不能保证数据报文的交付顺序,先发送的报文可能会更晚收到。

如果直接采用 UDP 协议来开发应用程序,就要自己解决好上面的两个主要问题。为了了解类似 TCP 这样的面向连接的可靠协议存在的必要性,我们来分析下基于 UDP 开发应用程序具体要怎样做。

因为数据包可能会被中间节点丢弃,而且发送端不会被通知。那么接收端在收到数据后必须予以回应,发送端收到回应才能知晓数据已发送成功。如果发送端一段时间后没有收到回应就可以认为,数据可能已被丢弃,接收端没有接收到数据,此时就要重新发送该数据。从上面的分析来看,发送端收不到接收端回应的原因有两个,要么数据被丢弃,要么回应被丢弃,无论是哪个,发送端都会选择重新发送数据。

这就带来了另一个数据重复问题,如果接收端已接收到数据,只是发出的回应被丢弃了,发送端会重发,此时接收端会再次收到该数据。如果接收端不能识别出这是重复的数据,就会造成应用程序出错。所以每次发送的数据包要有唯一编号,而且接收端在收到数据后不能立刻消费,必须先放到缓存里等待一段时间,在这段时间里,接收端如果遇到相同的数据包则丢弃,然后予以回应,发送端收到回应后确认数据已发送成功,继续处理其他数据包。

从上面的分析可知,由于发送端可能会重发数据,所以要有发送缓存。接收端为了避免接收重复数据,也要设置接收缓存。发送端的数据缓存时间取决于多长时间收到该数据包的回应,接收端的缓存时间取决于数据已接收完整,且发送端已收到回应。对于接收端的回应,发送端是不会再给予回应的,发送端只会继续发送其他数据。所以对于接收端来说,通常会设置较长一段时间,确保发送端已收到回应。但这不是百分之百的,极小的概率是刚刚删除接收缓存中的数据包,就收到了重复的数据,此时应用程序就会报错。

再来看另一个顺序问题,如果接收者按照接收到数据的先后顺序消费数据,几乎可以肯定一定会遇到数据无法正确解析的错误。就算网络情况理想,先发后至这样的事情也会发生。所以要给数据包从小到大递增编号。接收端根据编号来在缓存中排序,依次消费数据。

此时会遇到另一个问题,接收端后面和前面的编号都已经收到了,唯独中间有个编号迟迟未收到,此编号前的数据可以安全消费,此编号后的数据暂时不能消费,就会阻塞在这里。

而且数据包有长度限制,不能超过 MTU 大小,超过 MTU 大小的数据包很可能被默默丢弃。应用程序需要传输的数据可能是非常长的,一张 JPG 图片几百 KB 甚至 几 MB,不可能一个数据包发送出去,此时就要对数据进行分片,每个分片单独编号,按照编号从小到大依次发送,然后在接收端进行数据包重新组装。

只需要用 UDP 写过一次应用程序,就可以体会到上面诸多需要考虑的问题,以及 TCP 是怎样默默地解决掉了这些问题。使用 TCP 协议,应用程序开发者只需要建立并维持连接,然后写入或者读取字节流,发送或接收完成后关闭连接即可。但是 TCP 协议也有自己的问题,就是“队首则塞”,TCP 协议严格保证数据顺序,如果网络抖动丢包较多,所丢包的编号以及后面的编号都要重传,造成阻塞。即使后面的数据和前面的是独立的,没有依赖关系。TCP 协议是通过建立多个连接来解决这个问题的,不同的数据通过不同的连接发送,避免了被不相关的数据阻塞住。但是建立和管理一个 TCP 连接的成本是很高的,创建连接时延时很大,这个问题可以通过连接池解决。但是客户端维持一个连接池,服务端可能就要管理超大规模数量的连接,因为一个客户端就维持了多个连接,而服务端承载的客户端数量可能是几千万甚至上亿的,在内存中维持这么多的连接数据是非常消耗资源的。

有个好消息是 QUIC 协议已经正式发布了,主流浏览器和 Web Server 已经全部支持该协议了,QUIC 也是基于 UDP 实现的,拥有 TCP 几乎所有的好处,解决了“队首阻塞”问题,同时也有更好的传输性能。但是这个协议非常复杂,PDF 版本协议内容有 151 页之多。可见实现这样一个协议是非常困难的,好在有很多开源实现。

QUIC 除了复杂之外,也是很难定制的。我想定义实现一个更简单、且容易定制扩展的传输协议 UDPack,UDPack 是 UDP Packet 两个单词的缩写。如同两个单词的含义,UDPack 协议是基于 UDP 协议的数据包传输协议。