tools servidor servers query pinger estado dinnerbone checker python subprocess minecraft

servers - Python no puede comunicarse con el subproceso de un servidor de Minecraft



server pinger dinnerbone (1)

Estoy tratando de escribir un controlador / controlador para el servidor de Minecraft. Mi problema es que parece que no consigo que la escritura y la lectura funcionen correctamente. Cuando un cliente emite un comando que utiliza el método serverCom la clase del servidor, el texto / registro del servidor de Minecraft comienza a ingresar en la ventana / consola de Python de Python y el cliente conectado se bloquea. Además, parece que después de usar Popen , el servidor de Minecraft no se Popen realmente hasta que escribo en el servidor (también conocido serverCom método serverCom ). En caso de que alguien se esté preguntando, el Popen va a un archivo por lotes que abre el archivo .jar. Esto está en 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''s 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()


No tengo idea de cómo funciona un servidor de Minecraft, pero hay varios problemas con su código:

  • Está redirigiendo stderr a stdout desde el proceso Java creado, y luego espera una respuesta de línea del servidor. Esta podría ser la razón por la que el servidor de Minecraft no se inicia, ya que se bloquearía en una escritura estándar (según cómo lo maneje Windows XP) . Además, cualquier escritura stderr (por ejemplo, escritura de registro) destruirá cualquier respuesta estructurada que pueda estar esperando.

  • Estás leyendo con sock.recv(N) y luego asumiendo que obtienes todo el fragmento (por ejemplo, contraseña). No es así como funciona TCP, es muy posible que recupere un solo carácter (especialmente si el usuario escribe la contraseña de forma interactiva, por ejemplo, en un indicador de Telnet).

  • Está vaciando la salida estándar del subproceso , que es su flujo de entrada . Probablemente quieras eliminar la entrada estándar del subproceso. Vaciar un flujo de entrada no tiene sentido, es el flujo de salida el que determina cuándo se debe vaciar.