如何将数据发送到与当前请求处理程序不同的请求? (带有 ThreadingMixIn 的 Python SocketServer)

2024-01-11

我正在用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后,服务器如何通知both球员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()

可能有更好的方法来做到这一点,但我多年前为自己设计的方法(当我刚接触 Python 时!)是为每个客户都有一个收件箱。然后,每个客户端定期向服务器询问其收件箱中的内容,并相应地解析这些命令。

我会关注这个问题,我很想看到比我更好的方法。我还建议在尝试此操作之前等待答案。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将数据发送到与当前请求处理程序不同的请求? (带有 ThreadingMixIn 的 Python SocketServer) 的相关文章

随机推荐