Python套接字数据看起来像unicode,但无法转换

2024-09-27 09:25:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我是pythoncgi新手,想从php项目中翻译Minecraft MOTD脚本,该项目使用Socket从服务器获取数据

以下是我的源代码:

 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host = "example.com"
    port = 25565
    s.connect((host, port))
    s.sendall(b"\xFE\x01", 0)
    msg = s.recv(4096)
    s.close
    print(msg)

它可以连接到服务器并发回MOTD数据,但看起来很奇怪

b'\xff\x00>\x00\xa7\x001\x00\x00\x001\x002\x007\x00\x00\x00B\x00u\x00n\x00g\x00e\x00e\x00C\x00o\x00r\x00d\x00 \x001\x00.\x008\x00.\x00x\x00-\x001\x00.\x001\x002\x00.\x00x\x00\x00\x00\xa7\x00f\x00\xa7\x001\x00A\x00n\x00o\x00t\x00h\x00e\x00r\x00 \x00B\x00u\x00n\x00g\x00e\x00e\x00 \x00s\x00e\x00r\x00v\x00e\x00r\x00\x00\x006\x00\x00\x002\x000\x000' --> -->

我试着找到它是什么,它看起来像UTF-16 我试着用这个来解决问题:

msg.decode('UTF-16')

但遗憾的是,它没有起作用

UnicodeDecodeError: 'utf-16-le' codec can't decode byte 0x30 in position 126: truncated data 
      args = ('utf-16-le', b'\xff\x00>\x00\xa7\x001\x00\x00\x001\x002\x007\...0v\x00e\x00r\x00\x00\x006\x00\x00\x002\x000\x000', 126, 127, 'truncated data') 
      encoding = 'utf-16-le' 
      end = 127 
      object = b'\xff\x00>\x00\xa7\x001\x00\x00\x001\x002\x007\...0v\x00e\x00r\x00\x00\x006\x00\x00\x002\x000\x000' 
      reason = 'truncated data' 
      start = 126 
      with_traceback = <built-in method with_traceback of UnicodeDecodeError object>

Python无法将这些代码翻译成文本,这让我很困惑。 我是编程新手,有解决这个问题的办法吗?你知道吗


Tags: lemsgsocketutfx00xffx00rxa7
2条回答

你得到的是truncated data,因为你的数据确实被截断了。它的长度为127字节,从UTF-16解码它需要126或128字节的数据(即偶数字节)。你知道吗

删除后面的\x00字节并进行解码,得到以下结果:

>>> a = b'\xff\x00>\x00\xa7\x001\x00\x00\x001\x002\x007\x00\x00\x00B\x00u\x00n\x00g\x00e\x00e\x00C\x00o\x00r\x00d\x00 \x001\x00.\x008\x00.\x00x\x00-\x001\x00.\x001\x002\x00.\x00x\x00\x00\x00\xa7\x00f\x00\xa7\x001\x00A\x00n\x00o\x00t\x00h\x00e\x00r\x00 \x00B\x00u\x00n\x00g\x00e\x00e\x00 \x00s\x00e\x00r\x00v\x00e\x00r\x00\x00\x006\x00\x00\x002\x00'
>>> a.decode("utf-16")
u'\xff>\xa71\x00127\x00BungeeCord 1.8.x-1.12.x\x00\xa7f\xa71Another Bungee server\x006\x002'
>>> 

根据http://wiki.vg/Server_List_Ping#1.6,前三个字节是以下UTF-16BE字符串的数据包ID和大小:

Server to client

The server responds with a 0xFF kick packet. The packet begins with a single byte identifier ff, then a two-byte big endian short giving the length of the following string in characters. You can actually ignore the length because the server closes the connection after the response is sent.

After the first 3 bytes, the packet is a UTF-16BE string. It begins with two characters: §1, followed by a null character. On the wire these look like 00 a7 00 31 00 00.

The remainder is null character (that is 00 00) delimited fields:

  1. Protocol version (e.g. 74)
  2. Minecraft server version (e.g. 1.8.7)
  3. Message of the day (e.g. A Minecraft Server)
  4. Current player count
  5. Max players

所以去掉前三个字节,然后解码:

>>> data = b'\xff\x00>\x00\xa7\x001\x00\x00\x001\x002\x007\x00\x00\x00B\x00u\x00n\x00g\x00e\x00e\x00C\x00o\x00r\x00d\x00 \x001\x00.\x008\x00.\x00x\x00-\x001\x00.\x001\x002\x00.\x00x\x00\x00\x00\xa7\x00f\x00\xa7\x001\x00A\x00n\x00o\x00t\x00h\x00e\x00r\x00 \x00B\x00u\x00n\x00g\x00e\x00e\x00 \x00s\x00e\x00r\x00v\x00e\x00r\x00\x00\x006\x00\x00\x002\x000\x000'
>>> data[3:].decode('utf-16be').split('\x00')
['§1', '127', 'BungeeCord 1.8.x-1.12.x', '§f§1Another Bungee server', '6', '200']

相关问题 更多 >

    热门问题