消息分帧(字符串设计或协议设计)的两种形式
如果你读过Redis的源码,那么一定知道Redis的sds的设计。C语言中,字符串以 '\0'
结尾,printf
函数
遇到 '\0'
之后便会停止输出;而sds则是为字符串增加了一个长度,首先我们读取这个字符串长度为多少,然后
打印多少个字符。
这就是消息分帧中常见的两种形式:
- Length prefixing 预先放置长度,这种形式就是在真正的字符串之前放置一个长度,以表明字符串的长度。例如
10helloworld
。 这样做的好处是可以提前知道长度,然后再打印,获取字符串长度的时间复杂度为O(1)
。坏处是字符串长度有最大长度的限制, 而且由于不同的长度时,并不能全部使用到int
所占用的位,所以可能会造成一定的空间浪费,但是也有解决方案,可以看redis 最新的sds设计。此外,这种形式的设计是二进制安全的。 - Delimiters 分隔符,这种形式就和C语言中的一致,使用一个特殊的分隔符来代表终结。这种做法的好处在于节省空间,但是坏处也
很明显:非二进制安全;获取字符串长度的时间复杂度为
O(N)
。
这两种形式各有好坏。
前者在现实世界中的使用案例有Redis中的sds设计,HTTP/2协议,TCP协议,Redis通信协议等等多种协议;
后者在现实世界中的使用案例有UNIX系统中的文件(以EOF结束), C语言中的字符串(以\0
结束)等。
实际使用中,我们需要根据实际的场景来决定使用哪一种。
更多文章
本站热门
- socks5 协议详解
- zerotier简明教程
- 搞定面试中的系统设计题
- 用peewee代替SQLAlchemy
- frp 源码阅读与分析(一):流程和概念
- Golang(Go语言)中实现典型的fork调用
- DNSCrypt简明教程
- 一个Gunicorn worker数量引发的血案
- Golang validator使用教程
- Docker组件介绍(一):runc和containerd
- Docker组件介绍(二):shim, docker-init和docker-proxy
- 使用Go语言实现一个异步任务框架
- 协程(coroutine)简介 - 什么是协程?
- SQLAlchemy简明教程
- Go Module 简明教程