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

推荐订阅源

CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
D
Darknet – Hacking Tools, Hacker News & Cyber Security
F
Fortinet All Blogs
小众软件
小众软件
博客园_首页
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Microsoft Azure Blog
Microsoft Azure Blog
MongoDB | Blog
MongoDB | Blog
罗磊的独立博客
大猫的无限游戏
大猫的无限游戏
量子位
N
Netflix TechBlog - Medium
B
Blog
P
Proofpoint News Feed
月光博客
月光博客
Apple Machine Learning Research
Apple Machine Learning Research
人人都是产品经理
人人都是产品经理
云风的 BLOG
云风的 BLOG
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
腾讯CDC
Engineering at Meta
Engineering at Meta
Y
Y Combinator Blog
AI
AI
Stack Overflow Blog
Stack Overflow Blog
U
Unit 42
M
MIT News - Artificial intelligence
Vercel News
Vercel News
D
DataBreaches.Net
P
Palo Alto Networks Blog
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Cisco Talos Blog
Cisco Talos Blog
T
Threatpost
The Hacker News
The Hacker News
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Security Latest
Security Latest
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
有赞技术团队
有赞技术团队
Attack and Defense Labs
Attack and Defense Labs
Recent Announcements
Recent Announcements
Hugging Face - Blog
Hugging Face - Blog
Webroot Blog
Webroot Blog
Cyberwarzone
Cyberwarzone
美团技术团队
博客园 - 司徒正美
Cloudbric
Cloudbric
J
Java Code Geeks
T
Tailwind CSS Blog
The Last Watchdog
The Last Watchdog
A
About on SuperTechFans

设计

吐槽:为什么网上大多数时间戳转换工具网站都那么难用?又冗余又复杂 - V2EX 我如何用 AI · 网站设计 播播鸡 ✕ 元宝 开发了一个可以将图片转换为像素艺术的小工具 我的 Hugo 主题更新到 2.0 了 V2EX 主题设计大赛 New York $V2EX Token Concept DexScreener 网站的设计挺不错的 V 友有设计师么 [有奖问卷] 帮帮孩子的设计课!参与桌面收纳模块调查,赢 10 元红包/产品 Demo 搭建了个生活权益小程序,求宝贵建议! 想做一个 app 但是不懂设计,有什么好的工具推荐 有人搞了一个给照片加胡子的在线 AI 工具, 挺好玩的 draw.io 的创新用途 做了一个给图片添加矢量描边的 Figma 插件 - V2EX 有没有懂设计的,百度地图这个是对 less is more 的高级理解吗? AI 设计工具生成的页面要导入到 Figma、MasterGo、Pixso 等接着编辑,试试这个 iOS 产品设计:为什么国内大厂的输入框换行要隐藏在菜单里面, Return 设计为发送,然后输入框右边还有一个发送按钮 Elementary OS 的图标设计指南里的例图用的是什么工具? 88x31 badges by Louie Mantia 马上五一节都要开始做与五一有关的活动或则 PPT 文档了,这里收集了大量关于五一节的 PPT 模板,选好模板直接套文字就可以。 请问一下大家学设计有什么推荐的信息流 AI 跟艺术能碰撞出什么火花? 大家有推荐开发人员入门快的原型设计工具吗? 一个小而美的作品集网站 时间感知工具,专业工作者必备!正式公测,一年专业版派送中~ - V2EX deepseek 的 logo 有意思,包含了有 2 条鱼/2 个眼神 室内设计师们都用什么软件?效果图,安装图/施工图,🙏 推荐一款字体搭配 txt.dev · 一个很精致有趣的设计 - V2EX AI 设计神器 Recraft 有没有人关注一些硬件的设计 不是设计师,但有时候有些简单的 P 图,抠图之类的工作或制作一些小海报,有什么推荐的软件吗? - V2EX 全干工程师怎么入门 UI 设计 - V2EX 1024,送你们两张图片吧 - V2EX 为什么很多 ui 的背景设计不使用纯白? 而是使用 fafafa ? 当用计算机思维进行 Logo 设计时? - 思考过程 | D2Learn 开源社区 偏执的工程师思维,是不是设计不好一个产品特性?因为他总是用数学上的解 描述这个世界。 独立开发日记:一个删除交互的思考和设计 hitu 现在什么情况了呢?打不开了? photoshop2024 出现一个白色无法关闭? 分享一个 Figma 插件,设计师抄作业神器,可以导入任意网页到 Figma 里继续编辑 有什么好的笔记软件方便生成图片的么? 最近一直在找在学各种前端框架,现在我决定重新复习 HTML+CSS 欢迎大家来评价一下这个 debug 工具 如今还有哪些交互方式令人眼前一亮? 一个好的简约博客大概是什么样的呢? - V2EX V 友们有没有原型组件和模板分享的啊
设计了两个弹性长度数字编码,可以灵活地编解码数字以便高效传输
idrunk · 2025-01-14 · via 设计

DCE 是一个通用路由库,除了能路由 Http 等协议外,还能路由 Websocket 、Tcp 、Udp 等非标准可路由协议的协议,只需要实现定义的可路由接口即可。实现该接口需要序列化及反序列化数据包,为了实现一个高效灵活的二进制可路由协议,我设计了两个弹性数字编码。

7 比特弹性长度数字编码

一开始想着用第一个字节比特位标志表示是否有请求 ID 、请求路径等信息,第二个字节表示为扩展标志,来表示是否宽请求 ID 、长请求路径等。如在有或无扩展标志时,请求 ID 为 u32 或 u16 ,请求路径长度为 u16 或 u8 ,这样可以较为高效与灵活的编码请求头。对于请求的主体数据,它的长度不好确定,u8/u16/u32 都有可能,再用标志来表示的话需三个 bit ,且不是很灵活优雅,于是我设计了个 7 比特弹性长度数字编码来表示数据长度。

 0               1               2               3               4               5               6
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
|0|S|B|B|B|B|B|B|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-
|1|B|B|B|B|B|B|B|0|S|B|B|B|B|B|B|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-
|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|0|S|B|B|B|B|B|B|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-
|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|0|S|B|B|B|B|B|B|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-
|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|0|S|B|B|B|B|B|B|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-
|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|0|S|B|B|B|B|B|B|-|-|-|-|-|-|-|-
|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|0|S|B|B|B|B|B|B
|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B
|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B|1|B|B|B|B|B|B|B
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
 7               8               9               10              11              12              13
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|0|S|B|B|B|B|B|B|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|1|B|B|B|B|B|B|B|S|B|B|B|B|B|B|B|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

0:尾字节,1:非尾字节                                                                     S:符号位,B:二进制数字位

上面为 7 比特数字编码图。字节第 7 位为标志位,为1时表示还有下个字节,否则为尾字节。若为第九个字节,则没有标志位,这样最大可以用最多 9 个字节表示7*8+864 位数字,用最小一个字节表示 7 位数字,较为灵活且节省空间。字节序采用小端序,因为最高位字节可能为 8 比特数字位,而其他的字节皆为 7 比特,大端序需分情况来偏移运算,比较麻烦,而小端序则统一偏移 7 位即可,比较方便高效。

当写完这个 7 比特数字编解码算法后,发现实际应用还是有些不方便。首先用标志来表示宽窄数字不是很灵活,比如不支持 u64 的请求 ID 。其次解码数字时不太方便,无法一次性知道数字的字节长度,需要最多 9 次循环读取一个数字全部字节。针对第一个问题,将全部数字换成弹性数字即可,这样只需一个比特标记是否有,而无需标记长短。针对第二个问题,则需重新设计一个前缀式数字编码。

前缀式弹性数字编码

前缀式编码,即以第一个字节作为数字头部,存储数字字节长度信息,读取第一个字节后,就能将剩下字节一次性取出来而无需循环读取。这个前缀又不能只存长度信息,不然白白浪费了一个字节,可以在其高比特位存长度信息,低位存数字本体,于是基于这些需求设计了下图编码。

 0               1               2               3               4               5               6
 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
|0|S|B|B|B|B|B|B|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-     [int7]
|1|0|S|B|B|B|B|B|B|B|B|B|B|B|B|B|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-     [int14]
|1|1|0|S|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-     [int21]
|1|1|1|0|S|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-     [int28]
|1|1|1|1|0|S|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|-|-|-|-|-|-|-|-|-|-     [int35]
|1|1|1|1|1|0|S|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|-|-     [int42]
|1|1|1|1|1|1|0|S|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B     [int64]
|1|1|1|1|1|1|1|0|S|           保留,后续可表示 128 位数字, 最长 1+8+8=17 字节.                             S: 符号位
|1|1|1|1|1|1|1|1|             为其他情况保留.                                                   B: 二进制数字位
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
             7               8               9               10              11              12              13
 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|B|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

上图为前缀式弹性数字(后续将省略“前缀式”而直接简称为“弹性数字”)编码图。有一个固定的头部,其中第一个0为长度与数字本体分隔符,高位的1的个数表示躯体数字字节数,低位为符号与数字的高位部分。当头部高位以0开头时,剩余部分为 7 位整数,无符号最大 127 ,没有躯体部分。由于头部需一个分隔符占位,所以最大只能表示 56 位数字,为了支持 64 位数字,当头部高位的1的个数大于 5 时,直接视为 64 位数字,加头部共 9 个字节表示。由于 6 字节起的整数皆为万亿级别,很少用到,可以忽略其浪费的字节。头部剩余的可用标志位,为以后可能需要支持的 128 位数字作保留。

细心的朋友可能已经发现,这不是很像 UTF-8 吗?是的,这个方案是以 UTF-8 编码为灵感设计出来的,只是做了一些调整以支持 64 位数字的编码。UTF-8 需要表示的范围较小,且可能为了表现出较强的特征,躯体部分都以10开头,浪费了很多空间。而弹性数字编码,除了头部需占用比特位来表示字节长度外,躯体部分 8 比特全部表示数字,没有浪费。

二进制可路由协议

实现弹性数字编码后,就可以较优雅的实现 DCE 二进制可路由协议的编码了。总体分为三个部分:一个标志头,用以表示有哪些属性;一个数字部分,用以标注属性值长度或作为数字值;最后为按序追加的属性值部分。

 0               1               .               .               .
 0 1 2 3 4 5 6 7 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
+-+-+-+-+-+-+-+-+- - - - - - - - -  - - - - - - - - - - - - - - - - - - - - - - |
|I|P|S|C|M|L|N|R| LEN of| LEN of| LEN of| LEN of|  ID   |  CODE |NumPath| same  |
|D|A|I|O|S|O|P|S| Path  | Sid   | Msg   | Body  |FlexNum|FlexNum|FlexNum| order |
|E|T|D|D|G|A|A|V|FlexNum|FlexNum|FlexNum|FlexNum| HEAD  | HEAD  | HEAD  |FlexNum|
|N|H| |E| |D|T| | HEAD  | HEAD  | HEAD  | HEAD  |       |       |       | BODY  |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - - - - - - - - - - - - - - - - - - - - - - |
|      |     |     |                                                            |
| Path | Sid | Msg |                       Body Data ...                        |
|      |     |     |                                                            |
+-+-------------+-+-------------+-+-------------+-------------------------------+

上图为 DCE 弹性可路由协议包编码图。图中将弹性数字头与躯体分别堆在一起,是为了取到标志开启数量后,能一次性取出所有数字头部,继而一次性取出完整数字,提升编解码效率。在表示长度的数字中,0 是无意义的,标志未开启即为 0 长度,无需占用一个字节来表示。所以专门提供了长度编解码方法,将需编码与解码的长度减或加一,可以多表示一个有效长度,这在标注如十六进制 sha512 时非常有用,可以仅用 1 个字节( 7 比特头)来表示 128 的长度,节省了一个字节。

节省这一两个字节有用吗?通过 DCE 可路由协议,仅需 2 到 3 个字节,就能发起一个有效的类 GET 请求,而 HTTP 动辄需要成百上千字节,这在一些网络珍贵的场景是不可接受的,节省的每个字节都尤为珍贵。

相较其他协议的优势

要二进制省流量可以用 protobuf ,要灵活可以用 json ,为什么还要自己设计一个协议呢。这两者确实不错,DCE 也实现了基于它们的可路由协议。硬要说起来,protobuf 不够灵活,它的数字需固定长度,会浪费空间。除此之外有个最重要的原因,在 tcp 连接下,无法方便的从数据流中提取一个完整的 pb 或 json 包,需要借助分隔符或长度标注。分隔符无法同时做到高效与可靠,最靠谱的还是长度标注,而这个长度标注相当于需在外层再套一层协议,所以也需弹性数字来实现这层协议。


最后感谢你读到这里,上述的技术代码,可至DCE-GO查看。DCE-GO 初发布,欢迎体验。可能有 BUG 或可改进的地方,欢迎提出建议,欢迎协同开发。持续维护的 DCE 还有RUST 版本,该版本较旧,近期大概不会更新,但最终会同步,欢迎关注。