我正在用 Python 编写一个多人游戏服务器和客户端,使用内置的 SocketServer 的 TCPServer 和 ThreadingMixIn,因为它似乎比手动管理套接字和线程模块更容易。(为此,我想坚持使用内置模块。)它使用类似于 HTTP 通信 (GTP) 的协议。
仅涉及一个客户端的请求已经生效。如果客户端发送请求“ ”,服务器只需向该客户端GET /index.html GTP/0.2
响应“ ”。GTP/0.2 200 OK
但是如果客户端 A 和 B 之间正在进行游戏(如服务器状态中记录的那样)并且客户端 A 发送请求“ TURN <my turn info> GTP/0.2
”,那么在轮到玩家 A 之后,服务器如何通知玩家 A和B 更改?
到目前为止,这是我的代码的要点:
import SocketServer
import socket, threading # not yet used
class ThreadingGameServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
def __init__(self, server_address, RequestHandlerClass):
SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)
self.players = []
self.games = []
class GameRequestHandler(SocketServer.BaseRequestHandler):
def setup(self):
self.request_data = None
self.response_data = None
def handle(self):
while True:
self.request_data = self.request.recv(4096)
if not self.request_data:
break # Client disconnected
# delegate handling to do_GET, do_POST, etc
do_method = 'do_' + self.request_data.split()[0]
if not hasattr(self, do_method):
self.request.sendall("GTP/0.2 501 Not Implemented\r\n\r\n")
continue
try:
do = getattr(self, do_method)
do()
except Exception as e:
break
def do_GET(self):
body = '<contents of {}>'.format(self.my_request.param)
data = "GTP/0.2 200 OK\r\nContent-Length: {}\r\n\r\n{}".format(len(body), body)
self.request.sendall(data)
def do_LOGIN(self):
"""
Create a player with the requested username and this handler.
Add the player to self.server.players.
Respond with 200 OK, body "Welcome!, <username>".
"""
def do_PLAY(self):
"""
If the requested opponent is not logged in and ready to play, respond with 403 Forbidden.
Create a game with this player and the requested opponent.
Remove the two players from self.server.players.
Add the game to self.server.games.
Respond with 200 OK, body "Begin game with <opponent>".
How do I send "Begin game with <this player>" to the opponent as well?
"""
def do_TURN(self):
"""
If it is not this player's turn, respond with 403 Forbidden.
Modify the game's state in self.server.games, including making it be the opponent's turn.
Respond with 200 OK, body "<new game state>".
How do I send the response to the opponent as well?
"""
def do_EXIT(self):
"""
If this player is logged in, log them out.
If they are in a game, respond to their opponent with 200 OK, body "Game over" (how?).
End their request handler.
"""
class GameClient(object):
def __init__(self, server_address):
self.socket = socket.create_connection(server_address)
def run(self):
"""
Read user input, e.g. "> login foobar".
Send request to server, e.g. self.socket.sendall("LOGIN foobar GTP/0.2\r\n\r\n")
Get server's reply via self.socket.recv(4096)
Print the reply body, e.g. "Welcome, foobar!"
"""
# On the server machine
server = ThreadingGameServer((socket.gethostname(), 4242), GameRequestHandler)
server.serve_forever()
# On each client machine
client = GameClient(('server.mygame.com', 4242))
client.run()