簡體   English   中英

Python 無法與 Minecraft 服務器的子進程通信

[英]Python can't communicate with subprocess of a Minecraft server

我正在嘗試為 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'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()

我不知道 Minecraft 服務器是如何工作的,但是您的代碼存在許多問題:

  • 您正在將 stderr 從創建的 Java 進程重定向到 stdout,然后期待來自服務器的線路響應。 這可能是 Minecraft 服務器未啟動的原因,因為它會在 stderr 寫入時阻塞(取決於 Windows XP 的處理方式) 此外,任何 stderr 寫入(例如日志寫入)都會破壞您可能正在等待的任何結構化響應。

  • 您正在使用sock.recv(N)閱讀,然后假設您獲得了整個塊(例如密碼)。 這不是 TCP 的工作方式,您很可能只返回一個字符(尤其是如果用戶以交互方式鍵入密碼,例如在 Telnet 提示中)。

  • 您正在沖洗,這是你的輸入流的標准輸出。 您可能想要刷新子進程的標准輸入 刷新輸入流沒有意義,輸出流決定了何時刷新。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM