一种简易网络传输数据格式【替代json/xml】

网络传输数据格式可有多种选择,主要可分为三种:
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;


Guess you like

Origin blog.csdn.net/xk641018299/article/details/64526916