From 64978647120812a13948e2146de81281b38a54d5 Mon Sep 17 00:00:00 2001 From: Sam Moore Date: Sat, 20 Apr 2013 10:20:45 +0800 Subject: [PATCH] Making dedicated match making server Start server with `./qchess.py --server` Connect from clients with `./qchess --server=address` --- qchess/qchess.py | 92 ++++++++++++++++++++++++++++++++++++++---- qchess/src/Makefile | 2 +- qchess/src/graphics.py | 3 +- qchess/src/main.py | 25 ++++++++++-- qchess/src/network.py | 4 +- qchess/src/server.py | 58 ++++++++++++++++++++++++++ 6 files changed, 170 insertions(+), 14 deletions(-) create mode 100644 qchess/src/server.py diff --git a/qchess/qchess.py b/qchess/qchess.py index 899c477..f3d5793 100755 --- a/qchess/qchess.py +++ b/qchess/qchess.py @@ -1299,7 +1299,9 @@ class Network(): - + def close(self): + self.src.shutdown() + self.src.close() # --- network.py --- # import threading @@ -2251,6 +2253,7 @@ class GraphicsThread(StoppableThread): #print "Reject " + str(i) + str(event.pos) + " vs " + str(t) + # Function to pick players in a nice GUI way def SelectPlayers(self, players = []): @@ -2313,7 +2316,7 @@ class GraphicsThread(StoppableThread): time.sleep(1) p = None players.append(p) - elif choice == 2: + elif choice == 1: address = "" while address == "": self.board.display_grid(self.window, self.grid_sz) @@ -2340,6 +2343,64 @@ class GraphicsThread(StoppableThread): # --- graphics.py --- # +def dedicated_server(): + max_games = 4 + games = [] + while True: + # Get players + s = socket.socket() + s.bind(("0.0.0.0", 4562)) + s.listen(2) + ss = s.accept() + + debug("Got white player") + + g = subprocess.Popen(["python", "qchess.py", "@network::"+str(4700+len(games)), "@network::"+str(4700+len(games)), "--log="+"_".join(str(datetime.datetime.now()).split(" ")) + ".log"], stdout=subprocess.PIPE) + games.append(g) + + ss[0].send("white " + str(4700 + len(games)-1)) + ss[0].shutdown(socket.SHUT_RDWR) + ss[0].close() + + time.sleep(0.5) + ss = s.accept() + + debug("Got black player") + + ss[0].send("black " + str(4700 + len(games)-1)) + ss[0].shutdown(socket.SHUT_RDWR) + ss[0].close() + + s.shutdown(socket.SHUT_RDWR) + s.close() + + while len(games) > max_games: + ready = select.select(map(lambda e : e.stdout, games),[], [], None) + for r in ready: + s = r.readline().strip(" \r\n").split(" ") + if s[0] == "white" or s[0] == "black": + for g in games[:]: + if g.stdout == r: + games.remove(g) + +def client(addr): + + s = socket.socket() + s.connect((addr, 4562)) + + [colour,port] = s.recv(1024).strip(" \r\n").split(" ") + + debug("Colour: " + colour + ", port: " + port) + + s.shutdown(socket.SHUT_RDWR) + s.close() + + if colour == "white": + p = subprocess.Popen(["python", "qchess.py", "@human", "@network:"+addr+":"+port]) + else: + p = subprocess.Popen(["python", "qchess.py", "@network:"+addr+":"+port, "@human"]) + p.wait() + sys.exit(0)# --- server.py --- # #!/usr/bin/python -u # Do you know what the -u does? It unbuffers stdin and stdout @@ -2369,14 +2430,18 @@ def make_player(name, colour): if s[0] == "network": ip = None port = 4562 + #print str(s) if len(s) > 1: - ip = s[1] + if s[1] != "": + ip = s[1] + if len(s) > 2: + port = int(s[2]) if ip == None: if colour == "black": - port = 4563 + port += 1 elif colour == "white": - port = 4563 + port += 1 return NetworkPlayer(colour, Network((ip, port)), None) if s[0] == "internal": @@ -2477,7 +2542,13 @@ def main(argv): if len(f.split(":")) == 2: max_moves = int(f.split(":")[1]) - + + elif (arg[1] == '-' and arg[2:] == "server"): + if len(arg[2:].split("=") <= 1): + dedicated_server() + else: + client(arg[2:].split("=")[1]) + sys.exit(0) elif (arg[1] == '-' and arg[2:].split("=")[0] == "log"): # Log file if len(arg[2:].split("=")) == 1: @@ -2631,6 +2702,13 @@ def main(argv): sys.stdout.write(game.final_result + "\n") return error + + + + + + + # This is how python does a main() function... if __name__ == "__main__": @@ -2650,4 +2728,4 @@ if __name__ == "__main__": sys.exit(102) # --- main.py --- # -# EOF - created from make on Fri Apr 12 17:07:44 WST 2013 +# EOF - created from make on Sat Apr 20 10:20:13 WST 2013 diff --git a/qchess/src/Makefile b/qchess/src/Makefile index c7929ab..ec7747f 100644 --- a/qchess/src/Makefile +++ b/qchess/src/Makefile @@ -1,7 +1,7 @@ # Makefile that builds qchess.py from the component files TARGET = qchess.py -COMPONENTS = piece.py board.py player.py agent_bishop.py timeout_player.py network.py thread_util.py log.py game.py images.py graphics.py main.py +COMPONENTS = piece.py board.py player.py agent_bishop.py timeout_player.py network.py thread_util.py log.py game.py images.py graphics.py server.py main.py #COMPONENTS=$(shell ls *.py | tr '\t' '\n' | grep -v $(TARGET)) $(TARGET) : $(COMPONENTS) diff --git a/qchess/src/graphics.py b/qchess/src/graphics.py index fefcbf3..fcfc1b5 100644 --- a/qchess/src/graphics.py +++ b/qchess/src/graphics.py @@ -367,6 +367,7 @@ class GraphicsThread(StoppableThread): #print "Reject " + str(i) + str(event.pos) + " vs " + str(t) + # Function to pick players in a nice GUI way def SelectPlayers(self, players = []): @@ -429,7 +430,7 @@ class GraphicsThread(StoppableThread): time.sleep(1) p = None players.append(p) - elif choice == 2: + elif choice == 1: address = "" while address == "": self.board.display_grid(self.window, self.grid_sz) diff --git a/qchess/src/main.py b/qchess/src/main.py index f52cad0..90deec7 100644 --- a/qchess/src/main.py +++ b/qchess/src/main.py @@ -27,14 +27,18 @@ def make_player(name, colour): if s[0] == "network": ip = None port = 4562 + #print str(s) if len(s) > 1: - ip = s[1] + if s[1] != "": + ip = s[1] + if len(s) > 2: + port = int(s[2]) if ip == None: if colour == "black": - port = 4563 + port += 1 elif colour == "white": - port = 4563 + port += 1 return NetworkPlayer(colour, Network((ip, port)), None) if s[0] == "internal": @@ -135,7 +139,13 @@ def main(argv): if len(f.split(":")) == 2: max_moves = int(f.split(":")[1]) - + + elif (arg[1] == '-' and arg[2:] == "server"): + if len(arg[2:].split("=") <= 1): + dedicated_server() + else: + client(arg[2:].split("=")[1]) + sys.exit(0) elif (arg[1] == '-' and arg[2:].split("=")[0] == "log"): # Log file if len(arg[2:].split("=")) == 1: @@ -289,6 +299,13 @@ def main(argv): sys.stdout.write(game.final_result + "\n") return error + + + + + + + # This is how python does a main() function... if __name__ == "__main__": diff --git a/qchess/src/network.py b/qchess/src/network.py index 973160f..32a7b50 100644 --- a/qchess/src/network.py +++ b/qchess/src/network.py @@ -165,4 +165,6 @@ class Network(): - + def close(self): + self.src.shutdown() + self.src.close() diff --git a/qchess/src/server.py b/qchess/src/server.py new file mode 100644 index 0000000..95af126 --- /dev/null +++ b/qchess/src/server.py @@ -0,0 +1,58 @@ +def dedicated_server(): + max_games = 4 + games = [] + while True: + # Get players + s = socket.socket() + s.bind(("0.0.0.0", 4562)) + s.listen(2) + ss = s.accept() + + debug("Got white player") + + g = subprocess.Popen(["python", "qchess.py", "@network::"+str(4700+len(games)), "@network::"+str(4700+len(games)), "--log="+"_".join(str(datetime.datetime.now()).split(" ")) + ".log"], stdout=subprocess.PIPE) + games.append(g) + + ss[0].send("white " + str(4700 + len(games)-1)) + ss[0].shutdown(socket.SHUT_RDWR) + ss[0].close() + + time.sleep(0.5) + ss = s.accept() + + debug("Got black player") + + ss[0].send("black " + str(4700 + len(games)-1)) + ss[0].shutdown(socket.SHUT_RDWR) + ss[0].close() + + s.shutdown(socket.SHUT_RDWR) + s.close() + + while len(games) > max_games: + ready = select.select(map(lambda e : e.stdout, games),[], [], None) + for r in ready: + s = r.readline().strip(" \r\n").split(" ") + if s[0] == "white" or s[0] == "black": + for g in games[:]: + if g.stdout == r: + games.remove(g) + +def client(addr): + + s = socket.socket() + s.connect((addr, 4562)) + + [colour,port] = s.recv(1024).strip(" \r\n").split(" ") + + debug("Colour: " + colour + ", port: " + port) + + s.shutdown(socket.SHUT_RDWR) + s.close() + + if colour == "white": + p = subprocess.Popen(["python", "qchess.py", "@human", "@network:"+addr+":"+port]) + else: + p = subprocess.Popen(["python", "qchess.py", "@network:"+addr+":"+port, "@human"]) + p.wait() + sys.exit(0) \ No newline at end of file -- 2.20.1