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