Python与C++结构体交互
需求:根据接口规范,实现与服务端的数据交互
服务端结构体分包头、包体、包尾
包头C++结构体示例如下
1 typedef struct head 2 { 3 BYTE string1; 4 BYTE string2; //包类型 5 BYTE string3; //版本号,目前为0 6 char string4[33]; 7 int string5; 8 int string6; 9 unsigned int string7; //包头校验和,以上所有字段的crc32校验和 10 char string8; 11 char string9; 12 }protocol_head;
包体C++结构体示例如下
1 typedef struct body 2 { 3 char sessid[33]; 4 int datalen; 5 BYTE data[0]; 6 };
包尾C++结构体示例如下
1 // 包尾 - 粘包分割 2 typedef struct tag_protocol_tail 3 { 4 BYTE tail[4] 5 }protocol_tail;
根据包头结构体的要求,需要使用CRC32校验
1 unsigned int GetCRC32(const unsigned char *pbData, int nSize) 2 { 3 unsigned long Table[256]={0}; 4 unsigned long ulPolynomial = 0xEDB88320; 5 6 unsigned long dwCrc; 7 int i,j; 8 for(i = 0; i < 256; i++) 9 { 10 dwCrc = i; 11 for(j = 8; j > 0; j--) 12 { 13 if(dwCrc & 1) 14 dwCrc = (dwCrc >> 1) ^ ulPolynomial; 15 else 16 dwCrc >>= 1; 17 } 18 Table[i] = dwCrc; 19 } 20 21 unsigned long dwCrc32 = 0xFFFFFFFF; 22 int idx=0; 23 while(nSize--) 24 { 25 dwCrc32 = ((dwCrc32) >> 8) ^ Table[(pbData[idx]) ^ ((dwCrc32) & 0x000000FF)]; 26 idx++; 27 } 28 return ~dw
python 实现内容
struct中支持的格式如下表:
Format |
C Type |
Python |
字节数 |
x |
pad byte |
no value |
1 |
c |
char |
string of length 1 |
1 |
b |
signed char |
integer |
1 |
B |
unsigned char |
integer |
1 |
? |
_Bool |
bool |
1 |
h |
short |
integer |
2 |
H |
unsigned short |
integer |
2 |
i |
int |
integer |
4 |
I |
unsigned int |
integer or long |
4 |
l |
long |
integer |
4 |
L |
unsigned long |
long |
4 |
q |
long long |
long |
8 |
Q |
unsigned long long |
long |
8 |
f |
float |
float |
4 |
d |
double |
float |
8 |
s |
char[] |
string |
1 |
p |
char[] |
string |
1 |
P |
void * |
long |
举例C中常用:
int16=short --> h
uint32=unsigned int --> I
UInt64=unsigned long long --> Q
byte表示一个字节,对应C的unsigned char --> B
python中CRC32校验
1 def mycrc32(szString): 2 # 校验码 3 m_pdwCrc32Table = [0 for x in range(0, 256)] 4 dwPolynomial = 0xEDB88320 5 dwCrc = 0 6 for i in range(0, 255): 7 dwCrc = i 8 for j in [8, 7, 6, 5, 4, 3, 2, 1]: 9 if dwCrc & 1: 10 dwCrc = (dwCrc >> 1) ^ dwPolynomial 11 else: 12 dwCrc >>= 1 13 m_pdwCrc32Table[i] = dwCrc 14 dwCrc32 = 0xFFFFFFFFL 15 for i in szString: 16 b = ord(i) 17 dwCrc32 = ((dwCrc32) >> 8) ^ m_pdwCrc32Table[(b) ^ ((dwCrc32) & 0x000000FF)] 18 dwCrc32 = dwCrc32 ^ 0xFFFFFFFFL 19 return dwCrc32
C++和python关于CRC32代码传入参数如何理解?
根据上面C++代码内容,可以看到传入2位参数,它的第一位参数是整个包头+包体+包尾内容,第二位参数是整个包前多少位的长度需要校验
对于python代码,实际上只要传入需要校验的内容。
本文中需要传入的内容实际上是包头的的前6个字段,也就是包头的string1+string2+string3+string4+string5+string6
包头代码
1 # 包头, data为传入的包体,body_len是包体长度 2 def qzj_head(data, body_len): 3 string1 = 100 4 string2 = 1 5 string3 = 0 6 string4 = "6" 7 string5 = body_len 8 string6 = body_len 9 10 string1 = struct.pack('B', string1 ) 11 string2 = struct.pack('B', string2 ) 12 string3 = struct.pack('B', string3) 13 string4 = struct.pack('33s', string4 ) 14 string5 = struct.pack('i', string5 ) 15 string6 = struct.pack('i', string6 ) 16 17 string7_struct = string1+string2+string3+string4+string5+string6 # 前面的6个字段内容 18 string7_crc32 = des_key.mycrc32(headcrc_str) # crc32校验 19 string7 = struct.pack('I', string7_crc32) 20 string8 = 0 21 string9 = 0 22 string8 = struct.pack('B', string8) 23 string9 = struct.pack('B', string9) 24 25 request_head = string1+string2+string3+string4+string5+string6+string7+string8+string9+data 26 return request_head
包尾代码
1 # 包尾,data是传入的包头+包体 2 def qzj_tail(data): 3 tail1 = '\0' 4 tail2 = '\0' 5 tail3 = '\r' 6 tail4 = '\n' 7 tail1 = struct.pack('s', tail1) 8 tail2 = struct.pack('s', tail2) 9 tail3 = struct.pack('s', tail3) 10 tail4 = struct.pack('s', tail4) 11 request_tail = data+tail1+tail2+tail3+tail4 12 return request_tail
包体代码
1 # 包体, data是要发送的json数据 2 def body_100(data): 3 string1 = '' 4 string2 = len(data) 5 string3 = data 6 7 string1 = struct.pack('33s', string1) 8 string2 = struct.pack('i', string2) 9 string3 = struct.pack('%ds' % datalen_num, string3) 10 request_body = string1+string2+string3 11 return request_body, len(request_body)