Подтвердить что ты не робот

Python не может связываться с подпроцессом сервера Minecraft

Я пытаюсь написать обработчик/контроллер для сервера Minecraft. Моя проблема в том, что я не могу заставить писать и читать правильно работать. Когда клиент выдает команду, использующую метод класса сервера serverCom, текст/журнал сервера Minecraft начинает попадать в консоль Python/консоль Python и зависает подключенный клиент. Кроме того, кажется, что после использования Popen сервер Minecraft не запускается до тех пор, пока я не напишу на сервер (метод serverCom). В случае, если кто-то задается вопросом, Popen переходит к пакетному файлу, который открывает файл .jar. Это находится в Windows XP.

import subprocess
import os
import configobj
import socket
import threading
from time import sleep

config = configobj.ConfigObj("config.ini")
cHost = config["hostip"]
cPort = int(config["hostport"])
cBuffer = int(config["serverbuffer"])
cClients = int(config["numberofclients"])
cPassword = config["password"]

class server(object):
    def __init__(self):
        self.process = False
        self.folder = "C:\\servers\\minecraft-danny"
        self.max = configobj.ConfigObj("%s\\simpleserver.properties"%self.folder)["maxPlayers"]

    def serverStart(self):
        if not self.process:
            self.process = subprocess.Popen("java -Xmx1024m -Xms1024m -jar minecraft_server.jar nogui", cBuffer, None, subprocess.PIPE, subprocess.PIPE, subprocess.STDOUT, cwd = self.folder)
            return True
        return False

    def serverStop(self):
        if self.process:
            self.serverCom("stop")
            self.process = False
            return True
        return False

    def serverCom(self, text):
        if self.process:
            self.process.stdout.seek(2)
            self.process.stdin.write("%s\n"%text)
            self.process.stdin.flush()
            self.process.stdout.flush()
            return (str(self.process.stdout.readline()), True)
        return ("", False)

    def serverPlayers(self):
        if self.process:
            self.serverCom("list")
            x = self.serverCom(" ")[0].split(":")[3].replace("\n","").replace(" ","")
            if x == "":
                x = 0
            else:
                x = len(x.split(","))
            return (x, self.max)
        return (0,self.max)

serv = server()

def client(cnct, adr):
    global count
    try:
        dat = str(cnct.recv(cBuffer)).split(" ")
        ans = False
        if dat[0] == "start":
            print "Client %s:%s started the MC Server....."%(adr[0], adr[1])
            x = serv.serverStart()
            sleep(1)
            serv.serverCom(" ")
            serv.serverCom(" ")
            sleep(5)
            if x:
                ans = "Server is now online."
            else:
                ans = "Server is already online."
        elif dat[0] == "stop":
            print "Client %s:%s stopped the MC Server....."%(adr[0], adr[1])
            x = serv.serverStop()
            sleep(6)
            if x:
                ans = "Server is now offline."
            else:
                ans = "Server is already offline."
        elif dat[0] == "commun":
            print "Client %s:%s executed a command on the MC Server....."%(adr[0], adr[1])
            serv.serverCom(" ".join(dat[1:]))
            x = serv.serverCom(" ")
            if x[1]:
                ans = x[0]
            else:
                ans = "No return text, server is offline or not responding."
        elif dat[0] == "players":
            print "Client %s:%s recieved the player count from the MC Server....."%(adr[0], adr[1])
            pc = serv.serverPlayers()
            ans = "%s/%s"%(pc[0],pc[1])
        elif dat[0] == "help":
            print "Client %s:%s recieved the help list....."%(adr[0], adr[1])
            ans = "__________\nstart - Starts the server.\nstop - Stops the server.\ncommun <command> - Writes to server console.\nplayers - Returns player count.\nhelp - Shows this help.\nclose - Closes client connections.\n__________"
        elif dat[0] == "close":
            pass
        else:
            ans = "Command '%s' is not valid."%dat[0]
        if ans:
            cnct.send("PASS")
            cnct.send("%s\n"%ans)
            threading.Thread(target = client, args = (cnct, adr,)).start()
        else:
            cnct.send("DICN")
            cnct.send("Connection to server closed.\n")
            cnct.close()
            print "Client %s:%s disconnected....."%(adr[0], adr[1])
            if count:
                count -= 1
    except:
        cnct.close()
        print "Client %s:%s disconnected..... "%(adr[0], adr[1])
        if count:
            count -= 1

print "-MC Server Control Server v0.0.1 BETA-"
print "Starting up server....."
print "Connecting to socket....."
count = 0
sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sck.bind((cHost, cPort))
sck.listen(5)
print "Connected and listening on %s:%s....."%(cHost, cPort)
print "Setting up client listener, allowing %s clients to connect at a time....."%cClients
while True:
    for x in range(cClients):
        (cnct, adr) = sck.accept()
        print "Client %s:%s connected....."%(adr[0], adr[1])
        cnct.send("Welcome to MineCraft Server Control.\n\nPlease enter server control password.\n")
        ps = str(cnct.recv(cBuffer))
        if count < cClients:
            if ps == cPassword:
                cnct.send("CRRT")
                cnct.send("%s was correct.\nIf you need help type 'help'."%ps)
                count += 1
                threading.Thread(target = client, args = (cnct, adr,)).start()
            else:
                cnct.send("WRNG")
                cnct.send("%s wasn't the correct password, please try again."%ps)
                cnct.close()
                print "Client %s:%s rejected....."%(adr[0], adr[1])
        else:
            cnct.send("WRNG")
            cnct.send("Too many clients connected to MineCraft Server Control")
            cnct.close()
            print "Client %s:%s rejected....."%(adr[0], adr[1])

sck.close()
4b9b3361

Ответ 1

Я не знаю, как работает сервер Minecraft, но есть ряд проблем с вашим кодом:

  • Вы перенаправляете stderr в stdout из созданного Java-процесса, а затем ожидаете ответ строки с сервера. Это может быть причиной того, что сервер Minecraft не запускается, поскольку он блокирует запись stderr (в зависимости от того, как Windows XP справляется с ней). Кроме того, любая запись stderr (например, запись в журнале) уничтожит любые структурированные ответы, которые вы можете ожидать.

  • Вы читаете с помощью sock.recv(N), а затем считаете, что получаете весь фрагмент (например, пароль). Это не то, как работает TCP, вы можете получить только один символ назад (особенно это верно, если пользователь вводит пароль интерактивно, например, в приглашении Telnet).

  • Вы очищаете стандартный вывод подпроцесса, который является вашим входным потоком. Вероятно, вы хотите сбросить stdin подпроцесса. Промывка входного потока не имеет смысла, именно выходной поток определяет, когда нужно сбрасывать.