Отправка пакета входа на сервер Minecraft в Python не работает - PullRequest
3 голосов
/ 04 марта 2012

У меня есть следующий скрипт на Python. Он пытается подключиться к серверу MineCraft, сначала отправив «рукопожатие», а затем отправив запрос на вход в систему. Спецификации протокола можно найти здесь: http://wiki.vg/Protocol

В любом случае скрипт python работает нормально, и ошибок нет. Тем не менее, я справедливо использую, я неправильно кодировал второй пакет, так как при его отправке на консоли сервера ничего не появляется. Плеер не подключен или что-то еще. В конечном итоге время ожидания истекает, и соединение закрывается из-за того, что клиент не вошел в систему вовремя.

По сути, в любом случае, кто имеет опыт работы с struct.pack (), может помочь мне здесь. Я прокомментировал строку, где я не уверен, правильно ли я все кодировал. Подробная информация об упаковке данных приведена в ссылке выше.

Любая помощь будет очень оценена, я довольно невежествен с кодированием / упаковкой данных. (

import struct
import socket
import time
import urllib
import urllib2
host = "127.0.0.1"
port = 25566
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

logindata = {'user':'JackBeePee', 'password':'*******', 'version':'12'}
data = urllib.urlencode(logindata)
print('Sending data to login.minecraft.net...')
req = urllib2.Request('https://login.minecraft.net', data)
response = urllib2.urlopen(req)
returndata = response.read() 
returndata = returndata.split(":")
mcsessionid = returndata[3]
del req
del returndata
print("Session ID: " + mcsessionid)
data = {'user':u'JackBeePee','host':u'127.0.0.1','port':25566}


stringfmt = u'%(user)s;%(host)s:%(port)d'
string = stringfmt % data
structfmt = '>bh'
packetbytes = struct.pack(structfmt, 2, len(string))+string.encode('utf-16BE')
s.send(packetbytes)
connhash = s.recv(1024)
print("Connection Hash: " + connhash)
print('Sending data to http://session.minecraft.net/game/joinserver.jsp?user=JackBeePee&sessionId=' + mcsessionid + '&serverId=' + connhash + '...')
req = urllib.urlopen('http://session.minecraft.net/game/joinserver.jsp?user=JackBeePee&sessionId=' + mcsessionid + '&serverId=' + connhash)
returndata = req.read()
if(returndata == 'OK'):
    print('session.minecraft.net says everything is okay, proceeding to send data to server.')
else:
    print('Oops, something went wrong.')

time.sleep(5)

# All above here works perfectly.
enc_user = data['user'].encode('utf-16BE')
#This line is probably where something's going wrong:
packetbytes = struct.pack('>bih', 1, 23, len(data['user'])) + data['user'].encode('utf-16BE') + struct.pack('>hiibBB', 2,0,0,0,0,0)
print(len(packetbytes))
print('Sending ' + packetbytes + ' to server.')
s.send(packetbytes)

while True:
    data = s.recv(1024)
    if data:
        print(data)

1 Ответ

1 голос
/ 04 марта 2012

Кажется, вы не добавляете строку или пустые поля;

packetbytes = struct.pack('>bihshiibBB', 1, 23, len(data['user']), enc_user, 0, 0, 0, 0, 0, 0)

О втором h в формате упаковки длина строки Minecraft больше или равна 2 байта. Поэтому я предполагаю, что пустая строка - это просто short со значением 0.

Edit: Вышеупомянутый метод не работает; s нужна длина;

packfmt = '>bih{}shiibBB'.format(len(enc_user))
packetbytes = struct.pack(packfmt, 1, 23, len(data['user']), enc_user, 0, 0, 0, 0, 0, 0)
...