2011-01-31 13 views
19

ait alt süreci ile iletişim kuramaz. Benim problemim, yazı yazmam ve düzgün çalışmak için okuma yapamam. Bir istemci, sunucu sınıfının serverCom yöntemini kullanan bir komut yayımladığında, Minecraft sunucusunun metni/günlüğü Python penceresi/Python konsoluna gelmeye başlar ve bağlı istemci kilitlenir. Ayrıca, ben Popen kullandıktan sonra sunucuya (aka serverCom yöntemi) için yazıyorsunuz kadar Minecraft sunucu gerçekten başlatmak etmediğini görünüyor. Herkesin merak etmesi durumunda, Popen, .jar dosyasını açan bir toplu iş dosyasına gider. Bu Windows XP'de.Python Ben Minecraft sunucusu için bir işleyici/denetleyici yazmaya çalışıyorum bir Minecraft sunucusunun

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() 
+9

Sana tavsiye edebilir [Python'un PEP8: Python Kodu için Stil Kılavuzu] (http://www.python.org/dev/peps/pep-0008/)? – orftz

+1

İletişim kurmak için iletişim() kullanmanız gerektiği anlaşılıyor. [Bu soru] (http://stackoverflow.com/questions/163542) zombileri körfezde tutmanıza yardımcı olur. Ben 'çözemedim – pwan

+0

ya ben "asenkron ve non engelleme" ne zaman kendini düşündüm ve bana vurdu [Twisted] subprocess' (http://twistedmatrix.com/trac/)! Greg burada [ilginç soru] sahiptir (http://stackoverflow.com/questions/6105760/twisted-python-spawnprocess-getting-output-from-a-command) (http [Buraya bir süreç sarmalayıcı uygulayacağını nasıl]: //twistedmatrix.com/trac/browser/tags/releases/twisted-10.0.0//twisted/runner/procmon.py#L52) [İyi Şanslar] [minecraft.py]! [minecraft.py]: https://github.com/YellowOnion/minecraft.py/blob/master/minecraft.py –

cevap

2

Bir Minecraft sunucusu nasıl çalıştığını hiçbir fikrim yok, ama senin koduyla bir takım sorunlar vardır:

  • Sen oluşturulan Java sürecinden stdout'a Stderr yönlendiriyorsunuz, daha sonra bekliyor sunucudan hat cevabı. Bir şekilde hataları yazma üzerinde bloke etmekteyiz Bu (Windows XP bunun nasıl işleyeceğini bağlı olarak), Minecraft sunucusu başlayan olmadığını nedeni olabilir. Ek olarak, herhangi bir stderr yazımı (ör. Günlük yazma), beklediğiniz herhangi bir yapılandırılmış yanıtı yok edecektir.

  • Sen bütün öbek (örneğin parolası) almak varsayarak sonra sock.recv(N) ile okuduklarını ve. TCP bu şekilde çalışmaz, sadece bir karakter geri alabilir (özellikle kullanıcı şifreyi örneğin Telnet isteminde şifrelerse doğrudur).

  • Sen giriş akışıdır alt işlemi, stdout'unu yıkama yapıyorsanız. Büyük olasılıkla alt işlemin stdin'unu temizlemek istersiniz. Bir giriş akışının yıkanması bir anlam ifade etmez, ne zaman akıtılacağını belirleyen çıkış akışıdır.

İlgili konular