好的,我已经有了一个使用数据包进行通信的开源 Java 客户端/服务器程序。我正在尝试为该程序编写一个Python客户端,但数据包的内容似乎被压缩了。快速浏览源代码建议将 gzip 作为压缩模式(因为这是我能找到的代码中导入的唯一压缩模块),但是当我将其中一个数据包中的数据保存到wireshark中并尝试执行以下操作时
import gzip
f = gzip.open('compressed_file')
f.read()
它告诉我这不是 gzip 文件,因为 header 错误。有人可以告诉我我在这里做错了什么吗?保存时我是否更改或弄乱了格式?在尝试运行此 block 之前,是否需要从数据包中删除一些无关数据?
if (zipped) {
// XML encode the data and GZIP it.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Writer zipOut = new BufferedWriter(new OutputStreamWriter(
new GZIPOutputStream(baos)));
PacketEncoder.encodeData(packet, zipOut);
zipOut.close();
// Base64 encode the commpressed data.
// Please note, I couldn't get anything other than a
// straight stream-to-stream encoding to work.
byte[] zipData = baos.toByteArray();
ByteArrayOutputStream base64 = new ByteArrayOutputStream(
(4 * zipData.length + 2) / 3);
Base64.encode(new ByteArrayInputStream(zipData), base64, false);
编辑: 好的,抱歉,我有此处要求的信息。这是使用 Wireshark 监听不同计算机上两个正在运行的原始程序副本之间的通信来收集的。为了获取下面的十六进制流,我在 Wireshark 中使用了“复制 -> 十六进制(字节流)”选项。
001321cdc68ff4ce46e4f00d0800450000832a85400080061e51ac102cceac102cb004f8092a9909b32c10e81cb25018f734823e000001000000000000005 21f8b08000000000000005bf39681b59c85818121a0b4884138da272bb12c512f27312f5dcf3f292b35b9c47ac2b988f902c59a394c0c0c150540758c250c5c 2ea5b9b9950a2e89258900aa4c201a3f000000
我知道其中将包含字符串“Dummy Data”。我相信它还应该包含“Jonathanb”(我用来发送消息的玩家名称)和整数 80(据我从代码中收集到的信息,80 是“Chat”的命令 #)。
最佳答案
如果您透露以下信息,将会有很大帮助:
(0) 是什么让您得出“数据包的内容似乎被压缩”的结论
(1) 正在写入数据包的 (a) 源代码和 (b) 文档的 URL
(2)样本包的内容
(a) print repr(open('file_saved_from_wireshark', 'rb').read())
(b) 以防万一通过wireshark 进行的长途旅行使水变得浑浊,请将其插入到您的Python 客户端中:
打印repr(a_sample_packet)
(3) 您收到的准确错误消息(复制/粘贴)
OP 提供数据包的十六进制转储后更新
这段代码:
import binascii, sys, cStringIO, gzip, struct, zlib
# guff is allegedly a "packet", formatted as 2 hex characters per byte
guff = "001321cdc68ff4ce46e4f00d0800450000832a85400080061e51ac102cceac102cb004f8092a9909b32c10e81cb25018f734823e00000100000000000000521f8b08000000000000005bf39681b59c85818121a0b4884138da272bb12c512f27312f5dcf3f292b35b9c47ac2b988f902c59a394c0c0c150540758c250c5c2ea5b9b9950a2e89258900aa4c201a3f000000"
guff2 = binascii.unhexlify(guff)
print "raw input: len=%d repr=%r" % (len(guff2), guff2)
# gzip spec: http://www.faqs.org/rfcs/rfc1952.html
GZIP_HDR = "\x1F\x8B\x08"
gzpos = guff2.find(GZIP_HDR)
if gzpos == -1:
print "Can't find gzip header"
sys.exit(1)
print gzpos, "bytes before gzipped data"
gzipped = guff2[gzpos:]
packet_crc, packet_orig_len = struct.unpack("<II", gzipped[-8:])
print "packet_crc, packet_orig_len:", hex(packet_crc), packet_orig_len
fobj = cStringIO.StringIO(gzipped)
zf = gzip.GzipFile(fileobj=fobj)
payload = zf.read()
print "payload: len=%d repr=%r" % (len(payload), payload)
print "crc32(payload):", hex(zlib.crc32(payload))
使用 Python 2.6.4 运行时生成此输出(通过 Windows 的“命令提示符”终端包装在第 80 列):
raw input: len=145 repr="\x00\x13!\xcd\xc6\x8f\xf4\xceF\xe4\xf0\r\x08\x00E\x00\x
00\x83*\x85@\x00\x80\x06\x1eQ\xac\x10,\xce\xac\x10,\xb0\x04\xf8\t*\x99\t\xb3,\x1
0\xe8\x1c\xb2P\x18\xf74\x82>\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00R\x1f\x8b\x0
8\x00\x00\x00\x00\x00\x00\x00[\xf3\x96\x81\xb5\x9c\x85\x81\x81!\xa0\xb4\x88A8\xd
a'+\xb1,Q/'1/]\xcf?)+5\xb9\xc4z\xc2\xb9\x88\xf9\x02\xc5\x9a9L\x0c\x0c\x15\x05@u\
x8c%\x0c\\.\xa5\xb9\xb9\x95\n.\x89%\x89\x00\xaaL \x1a?\x00\x00\x00"
63 bytes before gzipped data
packet_crc, packet_orig_len: 0x1a204caa 63
payload: len=63 repr='\xac\xed\x00\x05w\x04\x00\x00\x00Pur\x00\x13[Ljava.lang.Ob
ject;\x90\xceX\x9f\x10s)l\x02\x00\x00xp\x00\x00\x00\x01t\x00\nDummy Data'
crc32(payload): 0x1a204caa
评论/问题:
该数据包长度为 145 字节;一个数据包约为 2900 字节的想法发生了什么?
该数据包是 63 字节的尚未分析的数据,后跟一个 82 字节的 gzip 流,该流解压缩(!)到 63 字节。 gzip 流之后没有数据 - 通过将数据包的最后 8 个字节与计算出的 gzip 值进行比较来验证。它包含预期的“虚拟数据”,但用户 ID“johnathonb”不存在(或已混淆或加密)。
数据包结构与我们猜测正在使用的代码不匹配(没有 XML,没有 base64)。
压缩后的数据包含字符串“java.lang.Object”,这可能是某些 java 序列化协议(protocol)的症状。 Lasciate ogni speranza,voi qu'entrate。
关于java - 使用 python 的 gzip 时出现问题/"How do I know what compression is being used?",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2122190/