TLV(Type-Length-Value)

背景

  在流式协议一章中,我们使用了固定长度头部来处理消息边界问题,但是固定长度头部按预定义的固定顺序有和长度排列,每个字段的位置和大小在协议设计时已经确定,无法动态调节。
示例:IP头部固定为20个字节,其中包含版本、TTL、源地址等字段,每个字段的位置和长度固定。

  那么,如果我们考虑后期协议的拓展,固定字段就很难做出调整,这样我们就必须设计多种协议,发布多个软件版本,不容易维护。由此,大佬们就提出来了TLV(Type-Length-Value)。

TLV

1.基本结构

  TLV每个字段按类型(Type)、长度(Length)、值(Value)三元组组织:
(1)Type字段

  • 作用:唯一标识数据类型,决定如何解析Value.
  • 编码规则

定长:通常1-4字节(如0x01表示整数,0x02表示字符串)。

(2)Length字段

  • 作用:明确Value的字节长度,避免解析时依赖分隔符。
  • **编码方式: **
    • 1.定长模式:固定长度(如1字节表示Value最大长度为255字节,4字节则表示最大长度为4GB)。
    • 2.变长模式(BER编码):
      • 若长度<=127,用1字节表示。
      • 若长度>127,则首字节最高位必须为1,低7位表示后续有多少字节来表示Value的长度。
      • 示例:BER编码下Length字段为0x82 0x01 0x2C,其中首字节0x821000 0010,其高位为1,剩余7位数值为2,表示首字节后续2位为Value的长度,即0x01 0x2C为300,表示Value的实际长度为300字节。

(3)Value字段

  • 作用:存储实际数据,格式由Type定义。
  • 常见类型:
    • 基础类型:整数(大小端)、浮点数、字符串。
    • 复合类型:数组、结构体,甚至是嵌套TLV。

示例
假设我们定义了一种TLV结构,其结构体定义如下:

struct TLV {
	uint8_t type;		// Type: 假设有三种类型分别为:整数(0x01),浮点数(0x02),字符串(0x03)
	uint16_t length;	// Length: 定长模式,固定2个字节大小来表示Value的长度,即最大长度为65535字节
	std::string value;	// Value: 实际数据内容
};

这里,我们给出以下TCP消息,然后以我们定义的TLV结构去解读一下。
[Type:0x03(1B) Length:0x0005(2B) Value:0x48656C6C6F(5B)]

1.Type:0x03(1B) ->表示类型为0x03,即为字符串类型,且该字段大小为1个字节(1B);
2.Length:0x0005(2B) ->表示长度为0x0005,即Value的长度为5个字节,该字段大小为2个字节(2B);
3.Value:0x48656C6C6F(5B) ->表示实际内容为0x48656C6C6F,因为类型是字符串,所以我们解析出来是"Hello"。

posted @ 2025-02-28 00:35  ydqun  阅读(489)  评论(0)    收藏  举报