TLV Type Length Value 机制
传统数据传输,不同情况下会容易做成数据收发错误
- 例如:不同系统 32 位元系统,16 位元系统 之间沟通,由于系统对 unsigned int 解释是不同,同一组数据在不同系统会出现不同结果
- 系统级别功能不同,导致数据结构差异,例如:系统 A 升级了,多支援2个数据,而系统 B,仍然是旧有结构
TLV 机制提出了解决方案
定义协议
T TLV Type (1 byte)
L Data Length (1 byte)
V Actual Data
例如:定义功能 A,用 132 代表
TLV Type 为 132
Data Length 为 4 (单组数据)
Actual Data XXXXX
例子数据
132
20
201392385
24
234946817
24
218169601
24
184615169
24
注:上面例子是 ip/mask length e.g. 11.1.1.1/24 11.1.1.1 在 c 语言里用 int 表示
TLV 解码例子
void decode_tlv_132(char *tlv_ptr) {
int tlv_type (int)*(tlb_ptr);
tlv_ptr++;
int data_length = (int)*(tlv_ptr);
int unit_tlv_size = get_unit_size(tlv_type); // e.g. 4
int i = 0;
tlv_ptr++;
char ip_address[4];
switch(tlv_type) {
case 132:
{
int n_units = data_length/unit_tlv_size;
for(i=0; i<n_units; i++) {
#if 0
unsigned int ip_address = *((unsigned int *)tlv_ptr);
#endif
memcpy(ip_address, tlv_ptr, 4);
tlv_ptr += 4;
char mask = *tlv_ptr;
tlv_ptr++;
}
}
break;
default:
{
tlv_ptr += data_length;
}
break;
}
}
重点
- #if 0 是传统容易出错和不支援新功能地方
- 使用 char 或 byte 不要使用基于系统的数据类型 例如: unsigned int
- 上面 default: 是对新功能的支援
序列化和反序列化例子
对于 TLV 机制,提供了数据序列化和反序列化参考
序列化
typedef struct serialized_buffer {
char *b;
int size;
int next;
} ser_buff_t;
void init_serialized_buffer(ser_buff_t **) {
(*b) = (ser_buff_t *)calloc(1, sizeof(ser_buff_t);
(*b)->b = calloc(1, SERIALIZE_BUFFER_DEFAULT_SZIE); // e.g. 100
(*b)->size = SERIALIZE_BUFFER_DEFAULT_SIZE;
(*b)->next = 0;
}
ser_buff_t *stream;
init_serialized_buffer(&stream);
void serialize_data(ser_buff_t *buff, char *data, int nbytes) {
int available_size = buff->size - buff->next;
char isResize = 0;
while(available_size < nbytes) {
buff->size = buff->size * 2;
available_size = buff->size - buff->next;
isResize = 1;
}
if(isResize == 0) {
memcpy((char *)buff->b + buff->next, data, nbytes);
buff->next += nbytes;
return;
}
buff->b = realloc(buff->b, buff->size);
memcpy((char *)buff->b + buff->next, data, nbytes);
buff->next += nbytes;
return;
}
- buff 为缓存
- buff->b 为当前位置
- buff->next 为下一组数据位置
- buff->size 为缓存大小
使用 序列化 例子
ser_buff_t *stream;
init_serialized_buffer(&stream);
char data = 132;
serialize_data(stream, &data, 1);
data = 20;
serialize_data(stream, &data, 1);
unsigned int ip = 201392385;
serialize_data(stream, &ip, 4);
char mask = 24;
serialize_data(stream, &mask, 1);
ip = 234946817;
serialize_data(stream, &ip, 4);
mask = 24;
serialize_data(stream, &mask, 1);
...
反序列化
void de_serialize_data(char *dest, ser_buff_t *b, int size) {
memcpy(dest, b->b + b->next, size);
b->next += size;
}
使用 反序列化 例子
unsigned int dest;
de_serialize_data((char *)&dest, b, 4);
- b 为 例如:经过网络接收到的 buffer