需求:根據接口規范,實現與服務端的數據交互
服務端結構體分包頭、包體、包尾
包頭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)
?