小技巧:变长结构体设计

小技巧:变长结构体设计

作者:BlogUpdater |  时间:2018-02-27 |  浏览:2774 |  评论已关闭 条评论

在设计网络协议过程中,一般会有数据包头和数据包体。通常情况下,数据包头和数据包体长度是固定的。但是在某些特殊场景下,需要传输的数据量不是固定的,这个时候,就需要在数据包体中引入变长结构体的设计了。以下是参考代码:

数据包头:

typedef struct _MsgHeader
{
	UINT m_nCmd;
	UINT m_nPadding;
} MsgHeader;

数据包体:

typedef struct _MsgBody
{
	struct _MsgBody()
	{
		m_nPayloadLen = 0;
	}

	UINT m_nPayloadLen;
	BYTE m_pPayload[0];
} MsgBody;

数据包:

typedef struct _Package
{
	MsgHeader m_header;
	MsgBody * m_body;
} Package;

这里使用到技巧是:在数据包体中定义了一个没有任何元素的字节数组,当构建数据包体时,我们需要动态分配堆内存并将包体成员m_pPayload指向此堆内存。如下的代码演示了,如何构建一个变长的数据包体:

例如,数据包体载荷长度设定为3个字节
int nPayloadLen = 3;
整个数据包体的长度定义如下:
int nBodyLen = sizeof(MsgBody) + nPayloadLen];

随机生成数据包体载荷
BYTE arrData[nPayloadLen] = {0x11, 0x22, 0x33};

分配堆内存并拷贝数据到数据包体
Package package;
package.m_body = reinterpret_cast(new BYTE[nBodyLen]);
memset(package.m_body, 0, nBodyLen);
package.m_body->m_nPayloadLen = nBodyLen;
memcpy(m_body->m_pPayload, arrData, nPayloadLen);

那么,使用此变长数据包体就变得简单了,代码如下:
MsgBody * pBody = reinterpret_cast(package.m_body);
BYTE a = pBody->m_pPayload[0];
BYTE b = pBody->m_pPayload[1];
BYTE c = pBody->m_pPayload[2];

此设计方法有时候会产生C4200警告,我们可以使用如下方法禁止此警告,
在变长结构体定义之前,添加如下语句即可
#pragma warning(disable : 4200)

标签:

评论已关闭。