面对网络协议,在组包拆包时,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

Python之struct模块的更多相关文章

  1. Python学习——struct模块的pack、unpack示例

    he struct module includes functions for converting between strings of bytes and native Python data t ...

  2. c语言write与python的struct模块交互

    以下讲的都是用二进制形式打开文件.网上有很多struct模块的文章,下面是我做的小实验. 1.对于c里面的fwrite写入一个单字节,写的就是它的二进制.如3,写入文件就是二进制0x03,它并不是3的 ...

  3. python中struct模块及packet和unpacket

    转自:http://www.cnblogs.com/gala/archive/2011/09/22/2184801.html 我们知道python只定义了6种数据类型,字符串,整数,浮点数,列表,元组 ...

  4. 【转】在Python的struct模块中进行数据格式转换的方法

    这篇文章主要介绍了在Python的struct模块中进行数据格式转换的方法,文中还给出了C语言和Python语言的数据类型比较,需要的朋友可以参考下 Python是一门非常简洁的语言,对于数据类型的表 ...

  5. day30 python学习 struct模块和 subprocess 模块

    import subprocess import struct aa=input('>>') obj=subprocess.Popen(aa,shell=True,#aa代表的是读取字符串 ...

  6. Python:struct模块的pack、unpack

    mport struct pack.unpack.pack_into.unpack_from 1 # ref: http://blog.csdn<a href="http://lib. ...

  7. python中struct模块

    # #********struct模块********# # 1.按照指定格式将Python数据转换为字符串,该字符串为字节流,如网络传输时, # 不能传输int,此时先将int转化为字节流,然后再发 ...

  8. Python的Struct模块

    python strtuct模块主要在Python中的值于C语言结构之间的转换.可用于处理存储在文件或网络连接(或其它来源)中的二进制数据. #!/usr/bin/env python # -*- c ...

  9. Python struct模块

    有的时候需要用python处理二进制数据,比如,存取文件,socket操作时.这时候,可以使用python的struct模块来完成.可以用 struct来处理c语言中的结构体. struct模块中最重 ...

随机推荐

  1. Nexus Repository Manager 3 远程命令执行漏洞(CVE-2019-7238)

    poc地址 https://github.com/magicming200/CVE-2019-7238_Nexus_RCE_Tool

  2. 大数据学习(19)—— Flume环境搭建

    系统要求 Java1.8或以上 内存要足够大 硬盘足够大 Agent对源和目的要有读写权限 Flume部署 我这8G内存的电脑之前搭建Hadoop.Hive和HBase已经苟延残喘了,怀疑会卡死,硬着 ...

  3. Spring源码解析之BeanFactoryPostProcessor(三)

    在上一章中笔者介绍了refresh()的<1>处是如何获取beanFactory对象,下面我们要来学习refresh()方法的<2>处是如何调用invokeBeanFactor ...

  4. C作用域

    任何一种编程中,作用域是程序中定义的变量所存在的区域,超过该区域变量就不能被访问.C 语言中有三个地方可以声明变量: 在函数或块内部的局部变量 在所有函数外部的全局变量 在形式参数的函数参数定义中 局 ...

  5. 8.算法竞赛中的常用JAVA API :Calendar日期类

    8.算法竞赛中的常用JAVA API :Calendar日期类 摘要 在蓝桥杯中有关于日期计算的问题,正好java中的Date类和Calendar类提供了对日期处理的一些方法.Date类大部分方法已经 ...

  6. 1009 Product of Polynomials (25分) 晚上脑子就是容易僵住

    #include<iostream> using namespace std; struct { int a; double b; }poly[1001]; double a[2001]; ...

  7. SpringBoot开发三

    需求介绍-SpringMVC 服务层的三层架构:表现层,业务层,数据层,浏览器访问服务器先访问表现层,期待表现层返回一些数据,表现层呢就访问业务层处理业务,而业务层在处理业务的时候会调用数据层请求数据 ...

  8. C#/VB.NET 将PDF转为OFD

    OFD,全称Open Fixed-layout Document ,是一种可存储.读取以及编辑的国家标准版式的电子文档格式,属于中国的一种自主文件格式,在安全性上有可靠保证.为突破国外技术在我们软硬件 ...

  9. 线程 Thread类 GIL锁 信号量 Event事件

    线程的开启方法 进程是操作系统调度的最小单位,一个进程最少有一个主线程,而一个进程中可以开启多个线程 from threading import Thread def task(): print('A ...

  10. 【现学现卖】th:href标签动态路径设置,thymeleaf获取session中的属性值

    update:2020-02-28:按道理来说这个功能在前后端分离的时候应该不怎么用的上,基本到现在我还是没遇到过有这样的需求,不过也是一种方法就是.th:href="@{/{role}/l ...