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.