socket通信之TLV传输协议

  • 了解TLV协议

TLV :即Tag(Type)-Length-Value,它包含三个域,第一个Tag为要封装的数据的类型域,第二个Length为封装的总的数据长度,第三个Value为要装入数据的值。其实就是一个简单的自定义通信协议,将要传送的数据进行编码组织将其发送出去的过程。想要了解的更细致,建议自己可以百度搜索学习,这里就不细述了。下面就以一个例子说一下装包和解包。

数据装包

装包的过程其实很简单,只要将你的数据按照包头(PACK_HEADER)、Tag(Type)-Length-Value、校验和的顺序将每个字节按十六进制的形式装进去,形成一个字节流发送出去,如下图:socket通信之TLV传输协议_第1张图片
PACK_HEADER自己定义(我定义为0xFD),大小通常为一个字节;Tag也是自己定义,通常为一个字节;Length的大小要看你的数据所占用的字节大小,它的大小为包头大小+Tag大小+Length大小+校验和大小+数据字节大小,自身一般占用一个字节;crc校验和一般占两个字节。crc校验有兴趣可以自己学习,本人也不是很懂,用别人的源码。知道了怎么装包,下面来解释一下**为什么要加包头和校验和进去:**举一个例子,如果我们不加头和尾,要发送的数据为0x01 0x03 0x3c,接收端就会按照Tag(Type)-Length-Value顺序进行解析,知道数据的类型为01,长度为3,值为3c。但是发送的过程中也有可能数据丢失或者混入了其他数据,这时数据有可能会变为0x00 0x01 0x56 0x03 0x23,这时接收端按照之前的顺序解析就会出错,当我们加上头的时候,接收端解析的时候会先找到包头,然后按顺序解析,但是这样还是有出错的可那,但是加上crc校验和之后,crc根据接收到的数据计算出一个校验和,用来和装包装进去的校验和进行比较,如果相同说明这一帧数据正确,接收端才会开始解析数据,如果不正确就不解析。下面是我将获取到的温度进行装包的代码:

int packtlv_temp(char *buf,int size,float temp)
105 {
106     unsigned short              crc16=0;
107     int                         packlen=0;
108     int                         ofset=0;
109     int                         data_len=2;
110 
111     int                         i,j;
112     float                       a;
113     if( !buf || !temp || size

数据解析

解析的过程没有装包那么容易,逻辑性很强而且过程很复杂,建议自己先画一个流程图,搞清解包时所有可能的情况,再来写代码。解包时首先要判断接收到的数据是否为空,在判断整个数据的长度是否比最小长度还要小,满足条件之后开始寻找头,遍历整个接收到数据,一直找到头再开始解析,解析的时候千万别以为就不会出错了,还要判断减去头后的大小是否小于2,小于2说明数据不完整,然后用crc校验,校验正确说明数据没问题可以解析。大概流程就是这样,完整的过程看流程图,如有大佬发现不完整,欢迎指正,共同学习。流程图如下:
socket通信之TLV传输协议_第2张图片
下面是代码:

83 int unpacktlv(char *buf,int bv)
 84 {
 85 
 86     int                   i;
 87     int                   tlv_len;
 88     char                  *ptr=NULL;
 89 
 90     float                 t=0.0;
 91     float                 n,m;
 92 
 93     unsigned short        crc16;
 94     unsigned short        crc;
 95 
 96     if( !buf )
 97     {
 98         printf("Invailed input!\n");
 99         return 0;
100     }
101 
102     if( buf==NULL )
103     {
104         printf("buf is NULL!\n");
105         return 0;
106     }
107     printf("buf is not NULL\n");
108 go_on:
109     if( bvTLV_MAX_SIZE )
139         {
140             printf("tlv_len is error!\n");
141             memmove(buf,&ptr[2+1],bv-i-2);
142             bv=bv-i-2;
143             goto go_on;
144         }
145 
146         printf("tlv_len is ture!\n");
147 
148         if( tlv_len>bv-i )
149         {
150             printf("Error!\n");
151             memmove(buf,ptr,bv-i);
152             return bv-i;
153         }
154 
155         crc16=crc_itu_t(MAGIC_CRC,(unsigned char*)ptr, tlv_len-2);
156         crc=bytes_to_ushort((unsigned char*)&ptr[tlv_len-2],2) ;
159         if( crc!=crc16 )
160         {
161             printf("crc is not ture!\n");
162             memmove(buf,&ptr[tlv_len],bv+tlv_len);
163             bv=bv+tlv_len;
164             goto go_on;
165         }
166         printf("crc is true!\n");
167 
168        m=ptr[3];
169        n=((float)ptr[4])/100;
170        //printf("%d\n",ptr[4]);
171        //printf("0x%02x \n",(unsigned char)ptr[4]);
172        t=m+n;
173 
174         printf("Temperature is:%f\n",t);
175         printf("\n");
176 
177         memmove(buf,&ptr[tlv_len],bv-i-tlv_len);
178         bv=bv-i-tlv_len;
179         goto go_on;
180     }
181     return 0;
182 }

你可能感兴趣的:(socket通信之TLV传输协议)