结构体与指针应用_封包构造与解析

image-20210928175610434

image-20210928180651334

image-20210928181047378

image-20210928181341416




封包:网络传输中的包
自定义协议如下:
4字节 命令类型
1字节 附加数据个数
4字节 保留字段




TLV结构
type - 1字节 1 - 代表字符串 2 - 二进制数据
length - 4字节大小
value - 值

// 构造数据
命令类型 110 保留字0填充
2个TLV 一个是字符串 hello 一个是字符串agp



封包要使用#pragma pack(1) 1字节对齐

#pragma pack()还原

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <stdio.h>
#include <Windows.h>

#pragma pack(1)
typedef struct
{
byte bType;
int ilength;
char* cValue;
}TLV;

typedef struct
{
int iCmdID;
byte bCount;
int iResolve;
TLV tlv[0];
}COMMAND;
#pragma pack()

// 发送命令函数
void SendCmd(void* pDate, int size);
void ParseCmd(void* pDate, int size);

// 命令类型 110 保留字0填充
// 2个TLV 一个是字符串 hello 一个是字符串agp
int main(void)
{
// 声明变量
TLV tl1;
TLV tl2;
char* pString1 = NULL;
char* pString2 = NULL;
COMMAND* pCmd = NULL;
int iCmdLength = 0;
int iTLVCount = 0;
memset(&tl1, 0, sizeof(TLV));
memset(&tl2, 0, sizeof(TLV));

// 构造字符串
pString1 = malloc(strlen("hello"));
memcpy(pString1, "hello", strlen("hello"));
pString2 = malloc(strlen("agp"));
memcpy(pString2, "agp", strlen("agp"));

// 构造tlv1
tl1.ilength = strlen("hello");
tl1.bType = 1;
tl1.cValue = pString1;

// 构造tlv2
tl2.ilength = strlen("agp");
tl2.bType = 1;
tl2.cValue = pString2;

// 构造发送包
iCmdLength = sizeof(COMMAND) + tl1.ilength + tl2.ilength + 2 * 5;
pCmd = malloc(iCmdLength);
pCmd->iCmdID = 110;
pCmd->bCount = 2;
pCmd->iResolve = 0;
memcpy((void*)((int)pCmd + sizeof(COMMAND)), &tl1, 5);
memcpy((void*)((int)pCmd + sizeof(COMMAND) + 5), tl1.cValue, tl1.ilength);
memcpy((void*)((int)pCmd + sizeof(COMMAND) + 5 + tl1.ilength), &tl2, 5);
memcpy((void*)((int)pCmd + sizeof(COMMAND) + 5 + tl1.ilength + 5), tl2.cValue, tl2.ilength);
SendCmd(pCmd,iCmdLength);

// 解析
ParseCmd(pCmd,iCmdLength);

system("pause");
return 0;
}

void* g_PDate = NULL;
void SendCmd(void* pDate, int size)
{
g_PDate = malloc(size);
memcpy(g_PDate, pDate, size);
}

void ParseCmd(void* pDate, int size)
{
int i = 0;
COMMAND* cmd = (COMMAND*)pDate;
TLV* ptl1 = malloc(sizeof(TLV));
TLV* ptl2 = malloc(sizeof(TLV));
char* pString1 = NULL;
char* pString2 = NULL;
memset(ptl1, 0, sizeof(TLV));
memset(ptl2, 0, sizeof(TLV));

printf("命令ID:%d\r\n", cmd->iCmdID);
printf("TLV个数:%d\r\n", cmd->bCount);
printf("保留字段:%d\r\n", cmd->iResolve);
printf("TLV数据--------------------\r\n");
ptl1 = (TLV*)((int)pDate + sizeof(COMMAND));
printf("TL1类型:%d\r\n", ptl1->bType);
printf("TL1长度:%d\r\n", ptl1->ilength);
pString1 = malloc(ptl1->ilength + 1);
memcpy(pString1, (void*)((int)ptl1 + sizeof(TLV) - 4), ptl1->ilength);
pString1[ptl1->ilength] = 0;
printf("TL1数据:%s\r\n", pString1);

ptl2 = (TLV*)((int)pDate + sizeof(COMMAND) + ptl1->ilength + sizeof(TLV) - 4);
printf("TL2类型:%d\r\n", ptl2->bType);
printf("TL2长度:%d\r\n", ptl2->ilength);
pString2 = malloc(ptl2->ilength + 1);
memcpy(pString2, (void*)((int)ptl2 + sizeof(TLV) - 4), ptl2->ilength);
pString2[ptl2->ilength] = 0;
printf("TL2数据:%s\r\n", pString2);
}