Python 网络字节转换

0 投票
3 回答
2460 浏览
提问于 2025-04-17 09:13

我正在尝试在一个基于网络的协议中实现CRC校验。

CRC的计算是通过PyCRC这个库来完成的。

PyCRC会为给定的数据包生成一个校验和,并返回像这样的结果:CB3D9FD1

但是当我尝试把它发送出去时,不知道为什么,Python会修改我的字符串,把它转换成ASCII再变成十六进制,比如:

Crc = "CB3D9FD1"
...
buffer = "\x41\x42\x43\x44"+crc
...
s.send(buffer)

在网络上传输时,我会看到:

\x41\x42\x43\x44***\x43\x42\x33\x44\x39\x46\x44\x31***

而不是:

 \x41\x42\x43\x44***\xCB\x3D\x9F\xD1***

有没有简单的方法来解决这个问题呢?

谢谢!

3 个回答

0

通过这样赋值:crc = "CB3D9FD1",你是在说把变量 crc 设为一个8字节的字符串。正如 @Bashwork 所说,你需要把它从十六进制字符串转换为数字,或者保持它是数字。你可以用0x来赋值,像这样:crc=0xCB3D9FD1,这样就能得到一个数字值。

pack("L",x) 的意思是我给你一个 x,它必须是一个整数,我希望你把它打包成一个无符号长整型
你会看到"struct.error: cannot convert argument to integer"的错误,因为你传给 pack("L",...) 的是一个字符串 "CB3D9FD1"。

想了解 "L"、"I" 和其他参数的意思,可以查阅这个文档:https://docs.python.org/2/library/struct.html

把 CRC 打包成长整型是可行的:这样你会得到64位的0填充(在我的电脑上,可能会有所不同)。

>>> from struct import pack
>>> crc=0xcb3d9fd1
>>> repr(crc)
'3409813457'
>>> pack("L", crc)
'\xd1\x9f=\xcb\x00\x00\x00\x00'
>>> print crc
3409813457

也许你想用 pack("I",...) 来获取32位。

>>> pack("I",crc)
'\xd1\x9f=\xcb'

如果尝试用 pack("L",...) 打包一个 CRC 字符串,会失败:

>>> crc = "CB3D9FD1"
>>> repr(crc)
"'CB3D9FD1'"
>>> pack("L", crc)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
struct.error: cannot convert argument to integer
0

如果你把CRC转换成了一个包含“CB3D9FD1”的字符串,那么正确的字节序列是0x43 0x42 0x33 0x44 0x39 0x46 0x44 0x31。不要把这个字符串再转换成其他形式,也不要把这个字符串当成十六进制来解析(每两个字符对应一个字节)。

2

其实,不要把你的CRC转换成ASCII格式。保持它为十六进制,然后使用 struct.pack把它打包成字节字符串:

buffer += struct.pack("L", crc)

撰写回答