Python之struct模塊


面對網絡協議,在組包拆包時,python提供了struct模塊,它可以幫助我們在python值和C語言的結構體之間相互轉換,下面一起來了解struct的具體用法。

假設,我們的網絡協議為消息id(unsigned short類型)及消息payload(unsigned int類型)組成,那么該如何進行組包拆包呢?如下例所示:

import struct

# 組包, 其中msg_id為0x1002、msg_payload為0x10070008
packet = struct.pack('>HI', 0x1002, 0x10070008)
print("packet: %s" % packet)
# 拆包
msg_id, msg_payload = struct.unpack_from('>HI', packet)
print("msg_id: %s , msg_payload: %s" % (hex(msg_id), hex(msg_payload)))

 運行結果:

packet: b'\x10\x02\x10\x07\x00\x08'
msg_id: 0x1002 , msg_payload: 0x10070008

上述例子中,我們用到了pack(format, v1, v2, ...)函數組包及unpack(format, buffer)函數拆包,它們指定的消息格式為'>HI',即以大端字節序排列的unsigned short+unsigned int數據。

關於字節順序的符號,官方定義如下:

關於格式類型的符號,官方定義如下:

 為了方便我們計算format的長度,比如上例中'>HI'的長度,struct提供了calcsize(format)函數供我們調用,如下例所示:

import struct

fmt_len = struct.calcsize('>HI')
print("格式長度: %s" % fmt_len)

運行結果:

格式長度: 6

下面,我們進一步來了解pack_into(format, buffer, offset, v1, v2, ...)函數unpack_from(format, buffer, offset=0)函數,它們在組包拆包時,可以指定所需的偏移量,這讓組包拆包變得更加靈活。本文第一個例子中,網絡協議為固定長度,但是更多時候,網絡協議是可變長度的。假設,網絡協議由消息id(unsigned short類型)、消息size(unsigned int類型)及可變長度的消息payload(若干個unsigned int類型)組成,那么該如何操作呢?下例將為大家解答。

import struct
import ctypes

def load_packet(msg_id, msg_size, msg_payload):
    packet = ctypes.create_string_buffer(msg_size)
    struct.pack_into('>HI', packet, 0, msg_id, msg_size)
    struct.pack_into('>%dH' % (int(msg_size-6)/2), packet, 6, *msg_payload)
    return packet

def unload_packet(packet):
    msg_id, msg_size = struct.unpack_from('>HI', packet, 0)
    msg_payload = struct.unpack_from('>%dH' % (int(msg_size-6)/2), packet, 6)
    return msg_id, msg_size, msg_payload

if __name__ == '__main__':
    packet = load_packet(0x1002, 12, (0x1003, 0x1004, 0x1005))
    print("packet: %s" % packet.raw)
    msg_id, msg_size, msg_payload = unload_packet(packet)
    print(hex(msg_id), msg_size, [hex(item) for item in msg_payload])

運行結果:

packet: b'\x10\x02\x00\x00\x00\x0c\x10\x03\x10\x04\x10\x05'
0x1002 12 ['0x1003', '0x1004', '0x1005']

 

參考資料

  • https://docs.python.org/zh-cn/3/library/struct.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM