网络传输数据格式可有多种选择,主要可分为三种:
1.自定义二进制;
2.提供序列化和反序列化库的开源协议【如protocol buffers,json,Thrift】;
3.文本化协议【如json,xml】
第1种需要自己实现;第2种需要引入第三方库;第3种传输效率很低。
本文提供一种简单的key-val数据封装,无需引入库,仅仅是一个简单的类,传输效率效率远高于第3种方式。名为 DatX。
DatX一定程度上只是提供了一种方案,起抛砖引玉的作用,但同时此处提供的DatX代码也是一个完整的,可直接引入工程使用的类。
// 添加数据
BOOL Put(char *szKey, int iVal);
BOOL Put(char *szKey, float fVal);
BOOL Put(char *szKey, void *pData, int nData);
// 反序列化
BOOL UnPack(void *pData, int nData);
// 获取第i个key名
char *GetKey(int i);
// 获取key所对应的val,类型为xty
xty operator[](int i);
xty operator[](char *szKey);
// 将返回DatX数据的二进制流,以及大小
void *Bytes();
int Total();
1.自定义二进制;
2.提供序列化和反序列化库的开源协议【如protocol buffers,json,Thrift】;
3.文本化协议【如json,xml】
第1种需要自己实现;第2种需要引入第三方库;第3种传输效率很低。
本文提供一种简单的key-val数据封装,无需引入库,仅仅是一个简单的类,传输效率效率远高于第3种方式。名为 DatX。
DatX一定程度上只是提供了一种方案,起抛砖引玉的作用,但同时此处提供的DatX代码也是一个完整的,可直接引入工程使用的类。
如果愿意使用,请保留类注释中的作者笔名[hicker]^_^
注意:由于未使用算法优化内存的分配,故每调用一次Put都会重新malloc/free内存。有必要可以自己实现一个内存分配算法
// 添加数据
BOOL Put(char *szKey, int iVal);
BOOL Put(char *szKey, float fVal);
BOOL Put(char *szKey, void *pData, int nData);
// 反序列化
BOOL UnPack(void *pData, int nData);
// 获取第i个key名
char *GetKey(int i);
// 获取key所对应的val,类型为xty
xty operator[](int i);
xty operator[](char *szKey);
// 将返回DatX数据的二进制流,以及大小
void *Bytes();
int Total();
代码如下,只有一个结构体DatX
DatX.h
/*************************************************************************
** Desc : 为避免使用json和xml做网络传输,实现一种简单key-val数据类型,
** 内存结构如下: [cnt|int_key|xty_key|int_dat|xty|xty_dat]
** cnt_seg: 数据个数段,iCnt,xCnt
** int_key_seg: int/float型key
** xty_key_seg: xty型key
** int_dat: int型数据区
** xty: xty区
** xty_dat: xty.p的数据区
** 【注意】DatX会自动将int型key/val保存在xty型key/val前
** Author : hicker@2017-3-19 11:11:57
*************************************************************************/
typedef struct tagDatX
{
tagDatX() :iCnt(0), xCnt(0), __p(NULL), __n(sizeof(iCnt) + sizeof(xCnt)), __p_cnt(NULL), __p_int_key(NULL), __p_xty_key(NULL), __p_int_dat(NULL), __p_xty(NULL), __p_xty_dat(NULL), __z_xty_dat(0){}
tagDatX(void *pData, int nData)
:iCnt(0), xCnt(0), __p(NULL), __n(sizeof(iCnt) + sizeof(xCnt)), __p_cnt(NULL), __p_int_key(NULL), __p_xty_key(NULL), __p_int_dat(NULL), __p_xty(NULL), __p_xty_dat(NULL), __z_xty_dat(0)
{
UnPack(pData, nData);
}
~tagDatX(){ if (__p) free((void*)__p); }
typedef struct tagxty
{
tagxty():p(NULL),l(0){}
char *ToChar(int *nLen = 0){ if (nLen)*nLen = l; return (char*)p; };
int ToInt(){ return l; };
float ToFloat(){ return *((float*)&l); };
private:
int p; // xty数据内存偏移量
int l; // xty数据大小
friend tagDatX;
}xty;
BOOL Put(char *szKey, int iVal)
{
// 保存旧偏移
save_old_ofs();
// 申请新内存
__n += __z_k + __z_i;
__p = (int)malloc(__n);
if (__p == NULL)
{
__p = __p_old;
__n = __n_old;
return FALSE;
}
memset((void*)__p, 0, __n);
iCnt++;
// 计算新偏移量
calc_new_ofs();
// __z_xty_dat;
// 保存旧数据
if (__p_old) save_old_dat();
// 保存新数据
((int*)__p_cnt)[0] = iCnt;
((int*)__p_cnt)[1] = xCnt;
strcpy((char*)(__p_int_key + iCnt_old*__z_k), szKey);
*(int*)(__p_int_dat + iCnt_old*__z_i) = iVal;
return TRUE;
}
BOOL Put(char *szKey, float fVal)
{
return Put(szKey, *(int*)&fVal);
}
BOOL Put(char *szKey, void *pData,int nData)
{
// 保存旧偏移
save_old_ofs();
// 申请新内存
__n += __z_k + __z_c+nData;
__p = (int)malloc(__n);
if (__p == NULL)
{
__p = __p_old;
__n = __n_old;
return FALSE;
}
memset((void*)__p, 0, __n);
xCnt++;
// 计算新偏移量
calc_new_ofs();
__z_xty_dat +=nData;
// 保存旧数据
if (__p_old) save_old_dat();
// 保存新数据
((int*)__p_cnt)[0] = iCnt;
((int*)__p_cnt)[1] = xCnt;
strcpy((char*)(__p_xty_key + xCnt_old*__z_k), szKey);
((int*)(__p_xty + __z_x*xCnt_old))[0] = __z_xty_dat_old;
((int*)(__p_xty + __z_x*xCnt_old))[1] = nData;
memcpy((void*)(__p_xty_dat + __z_xty_dat_old), pData, nData);
return TRUE;
}
BOOL UnPack(void *pData, int nData)
{
// 保存旧偏移
save_old_ofs();
// 申请新内存
__n = nData;
__p = (int)malloc(__n);
if (__p == NULL)
{
__p = __p_old;
__n = __n_old;
return FALSE;
}
memcpy((void*)__p, pData, __n);
// 解析 iCnt,xCnt
iCnt = ((int*)__p)[0];
xCnt = ((int*)__p)[1];
// 计算新偏移量
calc_new_ofs();
// 解析__z_xty_dat
for (int i = iCnt; i < iCnt + xCnt; i++)
__z_xty_dat += ((int*)(__p_xty + i*__z_x))[1];//((*this)[i]).l;
return TRUE;
}
char *GetKey(int i)
{
if (i < iCnt + xCnt)
{
return (char*)(__p_int_key + (i*__z_k));
}
return NULL;
};
xty operator[](int i)
{
xty x;
if (i < iCnt)
{
x.l = *(int*)(__p_int_dat + (i*__z_i));
}
else if (i < iCnt + xCnt)
{
//memcpy(&x, (void*)(__p_xty+((i-iCnt)*__z_x)), __z_x);
x.p = ((int*)(__p_xty + ((i - iCnt)*__z_x)))[0];
x.l = ((int*)(__p_xty + ((i - iCnt)*__z_x)))[1];
x.p += __p_xty_dat;
}
return x;
}
xty operator[](char *szKey)
{
xty x;
for (int i = 0; i < iCnt+xCnt; i++)
{
if (strcmp(szKey, (char*)(__p_int_key + (i*__z_k))) == 0)
return (*this)[i];
}
return x;
}
void *Bytes(){ return (void*)__p; }
int Total(){ return __n; }
private:
void save_old_ofs()
{// 保存旧偏移
__p_old = __p;
__n_old = __n;
__p_cnt_old = __p_cnt;
__p_int_key_old = __p_int_key;
__p_xty_key_old = __p_xty_key;
__p_int_dat_old = __p_int_dat;
__p_xty_old = __p_xty;
__p_xty_dat_old = __p_xty_dat;
__z_xty_dat_old = __z_xty_dat;
iCnt_old = iCnt;
xCnt_old = xCnt;
}
void save_old_dat()
{// 保存旧数据
memcpy((void*)__p_cnt, (void*)__p_cnt_old, __z_c);
memcpy((void*)__p_int_key, (void*)__p_int_key_old, __z_k*iCnt_old);
memcpy((void*)__p_xty_key, (void*)__p_xty_key_old, __z_k*xCnt_old);
memcpy((void*)__p_int_dat, (void*)__p_int_dat_old, __z_i*iCnt_old);
memcpy((void*)__p_xty, (void*)__p_xty_old, __z_x*xCnt_old);
memcpy((void*)__p_xty_dat, (void*)__p_xty_dat_old, __z_xty_dat_old);
free((void*)__p_old);
}
void calc_new_ofs()
{ // 计算新偏移量
__p_cnt = __p;
__p_int_key = __p_cnt + __z_c;
__p_xty_key = __p_int_key + __z_k*iCnt;
__p_int_dat = __p_xty_key + __z_k*xCnt;
__p_xty = __p_int_dat + __z_i*iCnt;
__p_xty_dat = __p_xty + __z_x*xCnt;
}
public:
int iCnt; // int/float 个数
int xCnt; // xty 个数
private:
static const int __z_k = 32; // szKey最大长度
static const int __z_c = sizeof(int) * 2; // 头大小[sizeof(iCnt) + sizeof(xCnt);]
static const int __z_i = sizeof(int); // int大小
static const int __z_x = sizeof(int) * 2; // xty大小[sizeof(xty::p)+sizeof(xty::l)]
// 各数据段偏移量
int __p_cnt;
int __p_int_key;
int __p_xty_key;
int __p_int_dat;
int __p_xty;
int __p_xty_dat;
int __z_xty_dat;
// 各数据段old偏移量
int __p_old ;
int __n_old;
int __p_cnt_old;
int __p_int_key_old;
int __p_xty_key_old;
int __p_int_dat_old;
int __p_xty_old;
int __p_xty_dat_old;
int __z_xty_dat_old;
int iCnt_old;
int xCnt_old;
int __p; // 内存起始地址
int __n; // 内存中的大小
}DatX;