对“协议”的理解
深入理解“通信协议”
何为协议
这里讲的协议是指通信上的协议,而非文案上签署的协议,不过有类似的意思
协议是一种用来完成某种功能的通信/交互方式
例如: 我们讲话使用的语言,使用中文的人不能与使用英文的人直接进行交流,因为他们语言不同(协议不同无法直接进行通信),如果不同语言得人想要进行沟通,必须有一名翻译作为中介者进行翻译(协议转换)。
协议并没有什么神秘之处,通信双方约定好的信息表达方式即是协议,我们现在来自创一个简单的协议。
26个英文字母,我们使用数字大小来代替字母进行传递信息,例如: 1代表a,2代表b, . 代表分隔,现在需要表达信息 hello ,转换为上面的数字表述则是 H8.E4.L12.L12.O15
,即 8.4.12.12.15
,如果我们与对方约定了上面的的这种信息表达方式,那么他看到8.4.12.12.15
就能明白这个是 hello
,这个信息表达方式
即是协议
!
当然,上面这种方式也可以看做是信息的一种简单加密,使用数字和. 替换了直接的字母表达。那么我们转到通信上来解释下协议。
从最底层开始分析协议
0 和 1 信号的产生
先从电路开始,我们以前初高中或者大学都学过电路,电路中有电压
这个概念,电压有高有低,假设现在有个电压是5V的电源,接在如下电路中:
当按钮按下时,输出端接通电源 + ,产生一个5V的高电压信号,按钮弹起时电路断开,输出端无信号输出,按钮按下和弹起
产生了2个有信号和无信号
2个状态,有信号表示1,无信号表示0,我们就可以用这个电路来输出 0 和 1
的电信号了!!
使用协议发送 0 和 1(bit)
计算机的世界都是由0和1组成的,因此我们这个电路可以作为信号的发送方来发送任何想要表达的信息了。当然只能输出0和1是没有意义的,只能只能告知对方0和1两个信息,为了传输更丰富的信息,还需要协议
来做约定。
上面的电路虽然能触发0和1,但如果是连续连续触发的话就变成了010101…,0和1必须是交替的,不能连续出现2个1或0,因此需要一种方法能够表示连续1或0信号。 我们知道,按下按钮时有时间的,那么可以加入时间维度来约束。
我们将按钮按下产生信号1的时间设定一个阈值,假设阈值为0.5s,如果一次按下的时间< 0.5S
就表示这个信号为0,反之信号为1,这样一看,是不是就能完美发出0和1的信号了!!
上面我们用来成功表达0和1数据的方式就是协议
,也是最底层的一种协议,这个协议约定的信号阈值是0.5S,我们也可以设置为任意时间,阈值越小,单位时间内所能传递的信息就越多,比如我想发送1 1 两个信号,阈值是0.5S的话意味着我最少需要>1S的时间才能把这个信号发送完毕,如果是阈值0.5ms,则只需要>1ms就能发出去。
发送一段字节
上面已经完成了单个bit的发送,我们知道1 byte = 8 bit
那么连续8次就完成一个字节的发送,现在我们要使用上面的电路发送字节0xf0 = 1111 0000
的流程是:
按下>=0.5s ~ 松开
~ 按下>=0.5s ~ 松开
~ 按下>=0.5s ~ 松开
~ 按下>=0.5s ~ 松开
按下<0.5s ~ 松开
~ 按下<0.5s ~ 松开
~ 按下<0.5s~ 松开
~ 按下<0.5s ~ 松开
循环8次就完成了0xf0
的发送。
发送一个完整的数据
我们已经完成了一段字节的发送,但是通常我们发送的信息是有边界的
,什么时候发送开始,什么时候发送完成了不知道,因此还需要一个协议来约定数据包的起始和结束
位置的标记,例如我们约定:
收到0x00代表数据包开始, 收到0xFF表示数据包发送结束
现在要发送数据 0x1A 0x45 0x88 0xF0
,那么加上起始结束标记则为 0x00 0x1A 0x45 0x88 0xF0 0xFF
,这样我们在软件代码中便可以通过起始和结束标记判断什么时候应该开始和停止记录数据,并且能丢弃在传输中由于干扰而丢失包头或者包尾的残缺数据包。
我们为数据加上 头标记 0x00 和 尾标记 0xFF,这也是一个协议,这个协议的作用是拆解出一段完整的数据。
数据校验
上面使用了头尾标记协议
来拆解出了一段数据包,那么如果数据包的中间段数据丢失如何知晓?没有办法吧,因此可以再把协议
升级一下,加入校验算法来判断数据包是否完整。在此我们使用一个简单的办法,在尾部加入一段校验位来判断数据包是否完整。
校验算法为: 数据部分字节值累加的和 取低 2字节,也就是说如果 携带的数据累加和不等于校验部分2字节值,那么表示该数据包不正确应该被丢弃。
例如:数据 0x1A 0x45 0x88 0xF0 0xAA
的累加和为 0x0281
,如果数据末端校验和部分不为 0x01 0x81
,则表示该包无效。
自此,我们已经从底层创建了一套能发送完整带校验功能数据包的传输协议
了。
协议分类
以上使用的协议为基于字节
的协议,例如常用的TCP/IP MQTT 之类,我们知道数据的表达方式除了字节还有字符,HTTP就是基于字符
的协议,我们能通过字符来分析HTTP协议通信时部分携带的信息,
例如f12
打开浏览器network
,查看HTTP请求信息
可以看到这些内容都是可直接阅读,而字节协议是很难直接一目了然,大多数情况下我们仍会选择字节协议,因为这样能节省很多带宽,传递更多的信息。
总结
所以说,协议并不是什么神秘高大上的东西,本文也不是为了讲解各种协议怎么解析,而是想用一个简单的例子来表述本质性的东西,一句话概括协议就是为了能完成某种通信所约定的一种信息表达方式
,部分协议可以相互嵌套,你可以用协议A携带协议B格式的数据,就像HTTP是基于TCP的应用层协议。