Python struct作为网络数据包(未知字节序列)

问题描述 投票:0回答:2

我正在研究Python中的服务器引擎,用于我在GameMaker Studio 2中制作的游戏。我目前在制作和发送数据包方面存在一些问题。

我已成功设法建立连接并发送第一个数据包,但是如果打包结构中的第一个字节等于某个值,我找不到按顺序发送数据的解决方案,然后将其他数据解压缩到给定的序列。

例:

types = 'hhh' #(message_id, x, y) example
message_id = 0
x = 200
y = 200
buffer = pack(types, 0,x, y)

在服务器端:

 data = conn.recv(BUFFER_SIZE)
    mid = unpack('h', data)[0]
    if not data: break

    if mid == 0:
        sequnce = 'hhh'
        x = unpack(sequnce, data)[1]
        y = unpack(sequnce, data)[2]
python struct network-programming
2个回答
2
投票

您的后续解码看起来会根据消息ID而有所不同?

如果是这样,您可能希望使用unpack_from,它允许您仅从数据中提取第一个成员(现在写入,您的初始unpack调用将生成异常,因为您正在处理的缓冲区大小不正确)。然后,您可以根据消息ID获得改变解包格式字符串的代码。该代码看起来像这样:

from struct import pack, unpack, unpack_from

while True:
    data = conn.recv(BUFFER_SIZE)
    # End of file, bail out of loop
    if not data: break

    mid = unpack_from('!h', data)[0]

    if mid == 0:
        # Message ID 0
        types = '!hhh'
        _, x, y = unpack(types, data)
        # Process message type 0
        ...
    elif mid == 1:
        types = '!hIIq'
        _, v, w, z = unpack(types, data)
        # Process message type 1
        ...
    elif mid == 2:
        ...

请注意,我们在每种情况下都会再次打包消息ID以及特定于ID的参数。如果你喜欢使用unpack_from的可选偏移参数,你可以避免这种情况:

x, y = unpack_from('!hh', data, offset=2)

另一个解释说明:如果要在两台不同的机器之间发送消息,则应考虑“字节序”(字节顺序)。并非所有机器都像x86一样是“小端”。因此,通常以某个定义的字节顺序发送整数和其他结构化数字 - 传统上一直是“网络字节顺序”(这是大端),但只要你是一致的,它们都是可以的。您可以通过在每个格式字符串前加上'!'来轻松完成此操作。或者如上所示'<'(你需要对两边的每个格式字符串都这样做)。

最后,上面的代码可能适用于简单的“玩具”应用程序,但随着您的程序范围和复杂性的增加,您应该意识到,不能保证您的单个recv调用实际上接收所有已发送的字节而不是其他字节(例如来自随后发送的缓冲区的字节)。换句话说,通常需要添加一个缓冲层,或者确保您已经收到并正在运行您想要的字节数。


0
投票

你能解压整个数据到列表,然后在循环中检查它的元素吗?打包3次是什么原因?我想,你可以解压缩一次,然后使用该列表 - 首先检查它的长度,如果不是空的 - >检查第一个元素 - >如果等于特殊的那个,继续列表解析。你有这样的尝试吗?

© www.soinside.com 2019 - 2024. All rights reserved.