我是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无法将这些代码翻译成文本,这让我很困惑。 我是编程新手,有没有解决这个问题的解决方案?
答案 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)分隔字段:
- 协议版本(例如74)
- Minecraft服务器版本(例如1.8.7)
- 当天的消息(例如A Minecraft服务器)
- 当前玩家数量
- Max球员
醇>
因此去掉前三个字节,然后解码:
>>> 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']