python 解码原始 udp 数据包的正确方法

python proper way to decode raw udp packet

我正在编写一个脚本来获取 Valve 的服务器信息(在线玩家、地图等) 我请求信息时收到的数据包是这样的:

'\xff\xff\xff\xffI\x11Stargate Central CAP SBEP\x00sb_wuwgalaxy_fix\x00garrysmod\x00Spacebuild\x00\xa0\x0f\n\x0c\x00dw\x00\x0114.09.08\x00\xb1\x87i\x06\xb4g\x17.\x15@\x01gm:spacebuild3\x00\xa0\x0f\x00\x00\x00\x00\x00\x00'

这可能会帮助您了解我正在尝试做的事情https://developer.valvesoftware.com/wiki/Server_queries#A2S_INFO

问题是,我不知道如何正确解码,获取字符串很容易,但我不知道如何获取其他类型,如 byte 和 short 例如 '\xa0\x0f'

现在我正在做多重拆分,但你知道是否有更好的方法吗?

Python 具有将 encoding/decoding 不同数据类型转换为字节的功能。看看 struct 包,函数 struct.pack()struct.unpack() 是你的朋友。

取自https://docs.python.org/2/library/struct.html

>>> from struct import *
>>> pack('hhl', 1, 2, 3)
'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)

unpack 函数的第一个参数定义了存储在第二个参数中的数据的格式。现在您需要将 valve 给出的描述转换为格式字符串。如果你想从一个数据字符串中解压 2 ​​个字节和一个 short(长度当然是 4 个字节),你可以这样做:

(first_byte, second_byte, the_short) = unpack("cc!h", data)

您必须自己小心,以获取数据字符串的正确部分(我不知道这些数字是否已签名,请务必注意这一点)。

您必须以不同方式执行的字符串(它们在这里以 null 结尾,所以如果您知道字符串开始并读取到第一个 "[=16=]" 字节,请开始)。

pack() 工作方式相反,将数据存储在字节字符串中。查看 python 文档中的示例并稍微尝试一下以了解它(例如,当元组为 returned/needed 时)。

struct 支持您获得正确的字节顺序,大部分时间是网络字节顺序,与您的系统不同。这当然只对多字节整数(如 short)是必需的 - 因此格式字符串 `"!h" 应该正确解压一个 short。