前言
由于跨平台或者跨语言数据传输中存在操作系统不同,大小端问题,字节对齐不一样等各种原因,所以我们需要对数据进行序列化处理
几种常用的序列号方式
- XML类似于HTML,与HTML很相似,但是用它来序列化对象的时候,就显得很复杂
- JSON使用起来很简单,他的产生来自于一种关联数组,其本质是采用“键值对”的方式描述对象
- Protocol Buffer是一个高效的数据化数据存储格式,用于结构化数据串行化,很适合做数据储存或RPC数据交换格式
- ASN.1抽象语法标记
ASN.1
定义:他是描述在网络上传输信息格式的标准方法,描述了一种对数据进行编码,传输,解码的数据格式,他提供了一套完整的描述对象的结构
ASN.1的两部分
- 一部分描述信息内数据,数据结构及序列格式(属性)
- 一部分描述如何将各部分组成消息(方法)
编码格式
TAG | LENGTH | VALUE |
---|---|---|
数据类型 | 数据长度 | 数据的值 |
数据类型的表示:他在内部用int来表示数据类型,使用的是位操作来表示数据类型
核心思路
他就是将每一个数据转化为TLV格式,然后通过链表这个数据结构将数据连接起来,最后将整个链表再打包为TLV格式,下面是一个TLV数据的结构体
typedef struct ITCAST_ANYBUF_ {
unsigned char *pData;
ITCAST_UINT32 dataLen;
ITCAST_UINT32 unusedBits; /* for bit string */
ITCAST_UINT32 memoryType;
ITCAST_UINT32 dataType;
struct ITCAST_ANYBUF_ *next; /* for sequence and set */
struct ITCAST_ANYBUF_ *prev;
}ITCAST_ANYBUF;
常用的API接口
ITCAST_INT DER_ItAsn1_WriteInteger(ITCAST_UINT32 integer, ITASN1_INTEGER **ppDerInteger);
函数说明:对整形数据进行编码操作
函数参数:
integer: 输入参数, 表示待编码的整形数据
ppDerInteger: 传输参数, 编码之后的数据
返回值:
成功或者失败
ITCAST_INT DER_ItAsn1_ReadInteger(ITASN1_INTEGER *pDerInteger, ITCAST_UINT32 *pInteger);
函数说明: 对整形数据解码
参数说明:
pDerInteger: 传入参数, 表示待解码的数据
pInteger: 传出参数, 表示解码之后的数据
返回值:
成功或者失败
ITCAST_ANYBUF p;
ITCAST_UINT32 aa;
例如: DER_ItAsn1_ReadInteger(&p, &aa);
ITCAST_INT DER_ItAsn1_WritePrintableString(ITASN1_PRINTABLESTRING *pPrintString, ITASN1_PRINTABLESTRING **ppDerPrintString);
函数说明:编码字符串数据
函数参数:
pPrintString: 输入参数, 表示要编码的数据
ppDerPrintString: 输出参数, 表示编码之后的数据
返回值:
成功或者失败
ITCAST_INT DER_ItAsn1_ReadPrintableString(ITASN1_PRINTABLESTRING *pDerPrintString, ITASN1_PRINTABLESTRING **ppPrintString);
函数说明: 解码函数, 将ANYCAST_ANYBUF类型解码到第二个参数
参数说明:
pDerPrintString: 输入参数, 表示待解码的数据
ppPrintString: 输出参数, 存放解码之后的数据
返回值:
成功或者失败
ITCAST_INT DER_ITCAST_String_To_AnyBuf(ITCAST_ANYBUF **pOriginBuf, unsigned char * strOrigin, int strOriginLen);
函数说明: 将char *---->ITCAST_ANYBUF类型
函数参数:
pOriginBuf: 传出参数, ITCAST_ANYBUF指针
strOrigin: 传入参数, 待转换的字符串
strOriginLen: 传入参数, strOrigin的字符串长度
返回值:
成功或者失败
int EncodeChar(char *pData, int dataLen, ITCAST_ANYBUF **outBuf);
函数说明: 将char *类型数据进行编码
函数参数:
pData: 输入参数, 指的是待编码的字符串
dataLen: 输入参数, 指的是pData的长度
outBuf: 输出参数, ITCAST_ANYBUF类型的数据, TLV格式
int DecodeChar(ITCAST_ANYBUF *inBuf, char **Data, int *pDataLen);
ITCAST_INT DER_ItAsn1_WriteSequence(ITASN1_SEQUENCE *pSequence, ITCAST_ANYBUF **ppDerSequence);
函数说明: 序列化链表, 将链表序列化成字节流数据
函数参数:
pSequence: 输入参数, 待序列化的数据
ppDerSequence: 输出参数, 序列化之后的数据
ITCAST_INT DER_ItAsn1_ReadSequence(ITCAST_ANYBUF *pDerSequence, ITASN1_SEQUENCE **ppSequence);
函数说明: 反序列化
参数说明:
pDerSequence:输入参数, 开始需要将char *—>ITCAST_ANYBUF类型
ppSequence: 输出参数, 获得链表头节点
ITCAST_INT DER_ITCAST_FreeQueue(ITCAST_ANYBUF *pAnyBuf);
释放内存
测试函数
typedef struct _Teacher
{
char name[64];
int age;
char *p;
long plen;
}Teacher;
*/
int encodeTeacher(Teacher * p, char ** outData, int * outlen)
{
ITCAST_ANYBUF *head = NULL;
ITCAST_ANYBUF *temp = NULL;
ITCAST_ANYBUF *next = NULL;
//编码name
//ITCAST_INT DER_ItAsn1_WritePrintableString(ITASN1_PRINTABLESTRING *pPrintString, ITASN1_PRINTABLESTRING **ppDerPrintString);
//char *---->ITCAST_ANYBUF
DER_ITCAST_String_To_AnyBuf(&temp, p->name, strlen(p->name)+1);
DER_ItAsn1_WritePrintableString(temp, &head);
DER_ITCAST_FreeQueue(temp);
next = head;
//编码age
DER_ItAsn1_WriteInteger(p->age, &next->next);
next = next->next;
//编码p
//int EncodeChar(char *pData, int dataLen, ITCAST_ANYBUF **outBuf);
EncodeChar(p->p, strlen(p->p)+1, &next->next);
next = next->next;
//编码plen
DER_ItAsn1_WriteInteger(p->plen, &next->next);
//序列化
DER_ItAsn1_WriteSequence(head, &temp);
//输出参数赋值
*outData = temp->pData;
*outlen = temp->dataLen;
//释放内存
DER_ITCAST_FreeQueue(head);
return 0;
}
int decodeTeacher(char * inData, int inLen, Teacher ** p)
{
ITCAST_ANYBUF *head = NULL;
ITCAST_ANYBUF *temp = NULL;
ITCAST_ANYBUF *next = NULL;
Teacher *pt = (Teacher *)malloc(sizeof(Teacher));
if (pt == NULL)
{
return -1;
}
//将inData反序列化成链表
//将char *--->ITCAST_ANYBUF类型
DER_ITCAST_String_To_AnyBuf(&temp, inData, inLen);
DER_ItAsn1_ReadSequence(temp, &head);
DER_ITCAST_FreeQueue(temp);
next = head;
//解码name
DER_ItAsn1_ReadPrintableString(next, &temp);
memcpy(pt->name, temp->pData, temp->dataLen);
next = next->next;
DER_ITCAST_FreeQueue(temp);
//解码age
DER_ItAsn1_ReadInteger(next, &pt->age);
next = next->next;
//解码p
int len = 0;
DecodeChar(next, &pt->p, &len);
next = next->next;
//解码plen
DER_ItAsn1_ReadInteger(next, &pt->plen);
//给输出参数赋值
*p = pt;
//释放内存
DER_ITCAST_FreeQueue(head);
return 0;
}
void freeTeacher(Teacher ** p)
{
if ((*p) != NULL)
{
if ((*p)->p != NULL)
{
free((*p)->p);
}
free(*p);
}
}