通过 sock.recv() 调用获取存储在 Python 的 socketserver.TCPServer 上的消息

发布于 2025-01-12 01:15:55 字数 3858 浏览 0 评论 0原文

我有以下简化的项目结构:

tcp-test-project/
|
+-- server.py
+-- client.py

server.py 包含以下内容:

from socketserver import ThreadingTCPServer, StreamRequestHandler

LOCALHOST = "127.0.0.1"
PORT = 8000


class MsgQueueServer:

    def __init__(self,  port):
        self.port = port
        self.msg_q = []

    def start(self):
        print(f"starting MsgQueueServer at {LOCALHOST}:{self.port}")
        with MsgQueueTCPServer((LOCALHOST, self.port), MyMessageHandler, self.msg_q) as server:
            server.serve_forever()


class MsgQueueTCPServer(ThreadingTCPServer):

    def __init__(self, host_port_tup, request_handler, msg_q):
        super().__init__(host_port_tup, request_handler)
        self.msg_q = msg_q


class MyMessageHandler(StreamRequestHandler):

    def handle(self):
        self.cmd, self.msg = self.rfile.readline().decode().split(":", maxsplit=1)
        self._get_cmd_handler()()

    def _get_cmd_handler(self):
        return {
            "/NEW": self._recv_message,
            "/GET": self._send_messages,
        }[self.cmd]

    def _recv_message(self):
        self.server.msg_q.append(self.msg)
        print(f"server message queue contains messages: {self.server.msg_q}")

    def _send_messages(self):
        print("sending messages in msg_q to client...")
        for msg in self.server.msg_q:
            self.wfile.write(bytes(msg, "utf-8"))


if __name__ == "__main__":
    server = MsgQueueServer(PORT)
    server.start()

client.py 是:

import socket


class MsgQueueClient:

    def __init__(self, server_addr):
        self.host, port = server_addr.split(":")
        self.port = int(port)

    def send_message(self, message):
        """Send a message to the server."""

        cmd = "/NEW"
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            sock.connect((self.host, self.port))
            sock.send(bytes(f"{cmd}:{message}", "utf-8"))
        print(f"sent message: '{message}' to MsgQueueServer at {self.host}:{self.port}")

    def get_messages(self):
        """Fetch a list of all messages stored by the server."""

        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            sock.connect((self.host, self.port))
            sock.send(bytes("/GET:", "utf-8"))

            print("waiting on message from server...")
            received = str(sock.recv(1024), "utf-8")
            print(received)


if __name__ == "__main__":
    server_addr = "127.0.0.1:8000"
    client = MsgQueueClient(server_addr)

    client.send_message("Hello")
    client.send_message("World")

    client.get_messages()

现在,在 shell 提示符下,项目根目录作为我的 CWD,我开始服务器:

$ python3 server.py
starting MsgQueueServer at 127.0.0.1:8000

在一个新的 shell 中,我运行客户端:

$ python3 client.py
sent message: 'Hello' to MsgQueueServer at 127.0.0.1:8000
sent message: 'World' to MsgQueueServer at 127.0.0.1:8000
waiting on message from server...

此时,如果我调出服务器进程的标准输出,我会看到以下内容:

$ python3 server.py
starting MsgQueueServer at 127.0.0.1:8000
server message queue contains messages: ['Hello']
server message queue contains messages: ['Hello', 'World']

因此,记录的打印语句表明从客户端发送到服务器的两条消息是服务器成功接收并存储到其msg_q 属性。但是,当我尝试通过在客户端中调用 sock.recv(1024) 来检索服务器上存储的消息时,它会阻塞并且不会继续进行通信。

我主要遵循Python文档中的socketserver.TCPServer示例这里。坦率地说,我没有看到我在这里遗漏了什么,导致我的例子不起作用。非常感谢任何帮助。

I have the following simplified project structure:

tcp-test-project/
|
+-- server.py
+-- client.py

server.py contains the following:

from socketserver import ThreadingTCPServer, StreamRequestHandler

LOCALHOST = "127.0.0.1"
PORT = 8000


class MsgQueueServer:

    def __init__(self,  port):
        self.port = port
        self.msg_q = []

    def start(self):
        print(f"starting MsgQueueServer at {LOCALHOST}:{self.port}")
        with MsgQueueTCPServer((LOCALHOST, self.port), MyMessageHandler, self.msg_q) as server:
            server.serve_forever()


class MsgQueueTCPServer(ThreadingTCPServer):

    def __init__(self, host_port_tup, request_handler, msg_q):
        super().__init__(host_port_tup, request_handler)
        self.msg_q = msg_q


class MyMessageHandler(StreamRequestHandler):

    def handle(self):
        self.cmd, self.msg = self.rfile.readline().decode().split(":", maxsplit=1)
        self._get_cmd_handler()()

    def _get_cmd_handler(self):
        return {
            "/NEW": self._recv_message,
            "/GET": self._send_messages,
        }[self.cmd]

    def _recv_message(self):
        self.server.msg_q.append(self.msg)
        print(f"server message queue contains messages: {self.server.msg_q}")

    def _send_messages(self):
        print("sending messages in msg_q to client...")
        for msg in self.server.msg_q:
            self.wfile.write(bytes(msg, "utf-8"))


if __name__ == "__main__":
    server = MsgQueueServer(PORT)
    server.start()

And client.py is:

import socket


class MsgQueueClient:

    def __init__(self, server_addr):
        self.host, port = server_addr.split(":")
        self.port = int(port)

    def send_message(self, message):
        """Send a message to the server."""

        cmd = "/NEW"
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            sock.connect((self.host, self.port))
            sock.send(bytes(f"{cmd}:{message}", "utf-8"))
        print(f"sent message: '{message}' to MsgQueueServer at {self.host}:{self.port}")

    def get_messages(self):
        """Fetch a list of all messages stored by the server."""

        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
            sock.connect((self.host, self.port))
            sock.send(bytes("/GET:", "utf-8"))

            print("waiting on message from server...")
            received = str(sock.recv(1024), "utf-8")
            print(received)


if __name__ == "__main__":
    server_addr = "127.0.0.1:8000"
    client = MsgQueueClient(server_addr)

    client.send_message("Hello")
    client.send_message("World")

    client.get_messages()

Now at a shell prompt with the project root as my CWD, I start the server:

$ python3 server.py
starting MsgQueueServer at 127.0.0.1:8000

In a new shell, I run the client:

$ python3 client.py
sent message: 'Hello' to MsgQueueServer at 127.0.0.1:8000
sent message: 'World' to MsgQueueServer at 127.0.0.1:8000
waiting on message from server...

At this point, if I bring up the stdout of the server process, I see the following:

$ python3 server.py
starting MsgQueueServer at 127.0.0.1:8000
server message queue contains messages: ['Hello']
server message queue contains messages: ['Hello', 'World']

So the logged print statements indicate that two messages sent from the client to the server were successfully received by the server and stored into its msg_q property. But when I try to retrieve those stored messages on the server through the call to sock.recv(1024) in the client, it blocks and won't proceed with the communication.

I mostly followed the socketserver.TCPServer example from Python's docs here. And to be frank, I'm not seeing what I'm missing here that makes my example not work. Any help is greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文