网络通信--协议设计
1 介绍
1.1 定义
-
通信协议:两个节点间信息交换的规则语法。
类比的话,国人间语言交流,普通话就是通信协议。 -
常见的有tcp,udo,http,sip等常见协议。
-
其中 7层 OSI 模型中应用层,开发者可以根据应用业务逻辑自定义协议
-
自定义协议时需要考虑确定报文长度的方式
(1)基于定界符(Delimiter-based):消息的结束由一个唯一的标记(unique marker)指出,即发送者在传输完数据后显式添加的一个特殊字节序列。这个特殊标记不能在传输的数据中出现。比如 EOF。
(2)显式长度(Explicit length):在变长字段或消息前附加一个固定大小的字段,用来指示该字段或消息中包含了多少字节。比如 TLV。
1.2 帧、数据报、数据包的区别和联系
- 数据帧(Frame):就是数据链路层的协议数据单元,它包括三部分:帧头,数据部分,帧尾。其中,帧头和帧尾包含一些必要的控制信息,比如同步信息、地址信息、差错控制信息等;数据部分则包含网络层传下来的数据,比如ip数据包。
- 数据包(Packet):TCP/IP协议通信传输中的数据单位,处于网络层,在局域网中,“包”是包含在“帧”里的。
- 数据报(Datagram):多用于网络层以上,面向无连接的数据传输,工作过程类似于报文交换。采用数据报方式传输时,被传输的分组称为数据报。
- 一般说来,数据链路层发出的数据包称为frame,地址是链路层的地址,如mac地址;网络层发出的数据包称为packet,地址是网络层地址,如ip地址;传输层发出的数据包称为segment/datagram,地址是传输层地址,如TCP的端口号。
- 二层的PDU叫做Frame;
IP的叫做Packet;
TCP的叫做Segment;
UDP的叫做Datagram。
2 TLV
2.1 TLV介绍
- TLV: TLV是指由数据的类型Tag,数据的长度Length,数据的值Value组成的结构体,几乎可以描任意数据类型,TLV的Value也可以是一个TLV结构,正因为这种嵌套的特性,可以让我们用来包装协议的实现。
2.2 TLV优缺点
- 优点:可扩展性、简单易学、 跨语言特性
- 缺点:因为其增加了2个额外的冗余信息,tag 和len,特别是如果协议大部分是基本数据类型int ,short, byte. 会浪费几倍存储空间。另外Value具体是什么含义,需要通信双方事先得到描述文档,即TLV不具备结构化和自解释特性。
- 跨语言特性
java或PHP的语言,没有无符号类型,与C/C++语言不同,会导致负数解析失败。对使用类型做了强制性约束。虽然带来了约束,但是带来通用型和简洁性,和跨语言性,于是有了一个类型(type)规范。
2.3 定长不定长
- 描述Value部分所占字节的个数,编码格式分两类:定长方式(DefiniteForm)和不定长方式(IndefiniteForm),其中定长方式又包括短形式与长形式。
- 短形式:
字节第7位为0,表示Length使用1个字节即可满足Value类型长度的描述,范围在0~127之间的。 - 长形式:
即Value类型的长度大于127时,Length需要多个字节来描述,这时第一个字节的第7位置为1,0~6位用来描述Length值占用的字节数,然后直将Length值转为byte后附在其后,如: Value大小占234个字节(11101010),由于大于127,这时Length需要使用两个字节来描述,10000001 11101010
2.4 CRC校验
2.4.1 介绍
CRC(循环冗余校验)校验确保没有字节跳变发生
2.4.2 CRC在线计算
(1)http://www.ip33.com/crc.html
(2)https://www.lammertbies.nl/comm/info/crc-calculation.html
2.4.3 MODBUS协议
- 上位机须按照MODBUS协议的命令格式发送数据(包括计算的CRC值),从机才能正确辨识数据。若无CRC值,从机将返回含有错误号的应答包,不会得到正确结果。标准的做法,发送前计算CRC值并一起发送,接收后也计算CRC值并与接收的校验码对比是否相等,以辨别数据是否准确。
- 参数模型:CRC 16/modbus
- 校验位计算
/*
* 函数名 :CRC16
* 描述 : 计算CRC16
* 输入 : ptr---数据,len---长度
* 输出 : 校验值
*/
UINT16 CRC16(UINT8 *ptr, UINT16 len)
{
unsigned char i;
unsigned short crc = 0xFFFF;
if (len == 0) {
len = 1;
}
while (len--) {
crc ^= *ptr;
for (i = 0; i<8; i++)
{
if (crc & 1) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
ptr++;
}
return(crc);
}
unsigned short UmUtil::Crc16(const unsigned char* buf, int count)
{
uint16_t crc = 0xffff;
while(count > 0)
{
crc = (crc >> 8) ^ CRC16_Table[(crc & 0xff) ^ *(buf++)];
count--;
}
return crc;
}
2.5 解析步骤
tlv报文的格式: [帧头] [Tag] [Length] [Value] [CRC校验和] (这里我用的CRC校验和是16位的所以占两个字节)
参考
1、通信协议之序列化
2、看懂通信协议:自定义通信协议设计之TLV编码应用
3、应用层通信协议开发浅析
4、浅谈自定义通讯协议——TLV
5、swoole学习笔记(五)网络通信协议设计 – EOF结束符协议和固定包头+包体协议
6、浅谈基于TCP和UDP的协议设计
7、TLV协议——实现封包与解析
8、TLV-简单的数据传输协议
9、【通信协议】帧、数据报、数据包的区别和联系
10、报文、帧、数据包等的区别
11、TLV简介以及c语言实现装包与解析–好
12、通信:成帧与解析
13、浅谈基于TCP和UDP的协议设计
14、关于modbus rtu协议的CRC(循环冗余校验)在线计算
15、Modbus通信CRC16校验程序
转载:https://blog.csdn.net/qq_38880380/article/details/102489550