Python Socket Data看起来像unicode但无法翻译

时间:2017-10-13 15:01:32

标签: python unicode

我是Python CGI的新手,想从我的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无法将这些代码翻译成文本,这让我很困惑。 我是编程新手,有没有解决这个问题的解决方案?

2 个答案:

答案 0 :(得分:1)

您获得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'
>>> 

答案 1 :(得分:0)

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

  

服务器到客户端

     

服务器以0xFF kick数据包响应。数据包以单字节标识符ff开头,然后是两字节   big endian short给出以下字符串的长度   字符。实际上你可以忽略长度,因为服务器   发送响应后关闭连接。

     

在前3个字节之后,数据包是UTF-16BE字符串。它始于   有两个字符:§1,后跟一个空字符。在电线上   这些看起来像00 a7 00 31 00 00

     

余数为空字符(即00 00)分隔字段:

     
      
  1. 协议版本(例如74)
  2.   
  3. Minecraft服务器版本(例如1.8.7)
  4.   
  5. 当天的消息(例如A Minecraft服务器)
  6.   
  7. 当前玩家数量
  8.   
  9. Max球员
  10.   

因此去掉前三个字节,然后解码:

>>> 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']