使用asyncore读取套接字缓存

1 投票
2 回答
1950 浏览
提问于 2025-04-15 16:25

我刚开始学习Python(之前在Java上编程已经有好几年了),现在正在做一个简单的基于socket的网络应用(纯粹是为了好玩)。我的想法是让代码连接到一个远程的TCP端点,然后监听从服务器发送到客户端的数据,并对这些数据进行一些解析。

从服务器推送到客户端的数据是UTF-8编码的文本,每一行的结束是用CRLF\x0D\x0A)来分隔的。你可能猜到了:客户端连接到服务器(直到用户手动取消),然后读取并解析接收到的每一行数据。

我已经成功实现了这个功能,不过我不太确定这样做是否完全正确。所以我有几个问题(代码会在后面提供):

  1. 在Python中这样做是对的吗(也就是说,真的这么简单吗)?
  2. 关于缓冲区和asyncore,有没有什么技巧、窍门或者有用的资源(除了参考文档)?

目前,数据的读取和缓冲是这样进行的:

def handle_read(self):
    self.ibuffer = b""

    while True:
        self.ibuffer += self.recv(self.buffer_size)
        if ByteUtils.ends_with_crlf(self.ibuffer):
            self.logger.debug("Got full line including CRLF")
            break
        else:
            self.logger.debug("Buffer not full yet (%s)", self.ibuffer)

    self.logger.debug("Filled up the buffer with line")
    print(str(self.ibuffer, encoding="UTF-8"))

ByteUtils.ends_with_crlf这个函数只是检查缓冲区的最后两个字节是否是\x0D\x0A。第一个问题是最主要的(答案基于这个),不过其他任何想法或建议我都很欢迎。谢谢。

2 个回答

6

其实更简单——你可以看看 asynchat 这个模块,还有它的 set_terminator 方法(以及这个模块里其他有用的内容)。虽然 Twisted 功能更强大、内容更丰富,但对于一些比较简单的任务来说,asyncore 和 asynchat(这两个模块可以很好的配合使用)确实非常简单易用,正如你已经开始发现的那样。

6

TCP是一种数据流,你不能保证你的缓冲区里不会同时包含一条消息的结束和下一条消息的开始。所以,仅仅在缓冲区的末尾检查\n\r并不能在所有情况下都有效。你需要逐个检查流中的每个字节。

我强烈建议你使用Twisted,而不是asyncore。可以参考下面的代码(记得这段代码是我记忆中的,可能需要调整才能直接使用):

from twisted.internet import reactor, protocol
from twisted.protocols.basic import LineReceiver


class MyHandler(LineReceiver):

    def lineReceived(self, line):
        print "Got line:", line


f = protocol.ClientFactory()
f.protocol = MyHandler
reactor.connectTCP("127.0.0.1", 4711, f)
reactor.run()

撰写回答