数据分包处理

#ifndef __DIVPACK_H__
#define __DIVPACK_H__

#pragma once


typedef int (*pfnProcessPackCallback)(const char*, int, void*);

class TDivPack
{
public:
	TDivPack()
	{
		maxlen = 0;
		szpack = NULL;
		Reset();
	}
	~TDivPack()
	{
		if(szpack != NULL)
		{
			free(szpack);
			szpack = NULL;
		}
	}

	void Reset()
	{
		bunbroken=true;
		npacklen = 0;
		ncurlen = 0;
		nleftlen = 0;
	}

	void DivPack(const char* pbuf, int nsize, pfnProcessPackCallback ProcessCallback, void* pVoid)
	{
		if(nsize <= 0)
			return;

		if(!bunbroken)
		{
			// 当前包数据没有接收完全,继续处理接收
			// 首先计算前一个包还需要多少数据
			int nleft = npacklen - ncurlen;
			if(nleft > nsize)
			{
				// 如果当前包还能容纳的数据大于传入的数据,将数据附加到当前包尾
				memcpy(szpack+ncurlen, pbuf, nsize);
				// 更新当前包的接收长度
				ncurlen += nsize;
			}
			else
			{
				// 如果当前包还能容纳的数据小于或等于传入的数据,将数据附加到当前包尾
				memcpy(szpack+ncurlen, pbuf, nleft);
				// 标记产生一个完整的包, 进行处理
				if(ProcessCallback != NULL)
				{
					(*ProcessCallback)(szpack, npacklen, pVoid);
				}

				bunbroken = true;
				npacklen = 0;
				// 继续处理剩余数据
				DivPack(pbuf+nleft, nsize - nleft, ProcessCallback, pVoid);
			}
		}
		else
		{
			// 重置当前包的数据标记
			ncurlen = 0;
			bunbroken = true;

			if( nsize < (4-nleftlen) )
			{
				// 如果当前传入的数据长度小于 解析包长度所需的字节数,保存数据
				memcpy(((char*)&npacklen)+nleftlen, pbuf, 4-nleftlen);	
				nleftlen += nsize;
				return;
			}

			// 解析数据包长度
			memcpy(((char*)&npacklen)+nleftlen, pbuf, 4-nleftlen);

			// 创建数据缓存,并初始化0
			if(szpack == NULL)
			{
				szpack = (char*)malloc(npacklen);
				maxlen = npacklen;
			}

			// 为减少内存分配次数,当包长度大于当前缓存长度时才重新分配
			if(npacklen > maxlen)
			{
				szpack = (char*)realloc(szpack, npacklen);
			}
			
			memset(szpack, 0, npacklen);

			// 记录实际数据包偏移
			int noffset = 4-nleftlen;
			nleftlen = 0;

			// 计算传入数据包剩余长度
			int nleft = nsize - noffset;

			if(nleft < npacklen)
			{
				// 如果传入的长度小于数据包长度
				// 设置数据包位不完整包,并记录已缓存的数据长度
				ncurlen = nleft;
				bunbroken = false;
				// 拷贝数据
				memcpy(szpack, pbuf+4, nleft);
			}
			else
			{
				// 如果传入长度大于数据包长度,拷贝数据
				memcpy(szpack, pbuf+noffset, npacklen);
				// 标记产生一个完整的包, 进行处理
				if(ProcessCallback != NULL)
				{
					(*ProcessCallback)(szpack, npacklen, pVoid);
				}
				bunbroken = true;
				int ntemplen = npacklen;
				npacklen = 0;
				// 继续处理剩余数据
				DivPack(pbuf+ntemplen+noffset, nsize-ntemplen-noffset, ProcessCallback, pVoid);
			}
		}
	}

private:
	char* 	szpack;
	bool 	bunbroken;
	int 	npacklen;
	int 	ncurlen;
	int 	nleftlen;
	int 	maxlen;
};


#endif // __DIVPACK_H__
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值