我经常编写简单的python TCP服务器,它们在解析长度前缀的数据包后响应请求。假设套接字已设置,通常看起来很像这样:
def tcp_server_loop():
msg = ''
msg_len = 0
while True:
msg += sock.recv(4096)
if len(msg) >= 4 and msg_len == 0:
msg_len, = struct.unpack_from("!I", msg)
if len(msg) >= msg_len:
protocol.parse_packet(msg[:msg_len])
msg = msg[msg_len:]
msg_len = 0
这很有效,并且很好地服务了我很多次,但我总是对msg += sock.recv(4096)
中附加的字符串感到厌烦。对于小数据包,这不是太糟糕,因为为这些小字符串分配新存储的开销并不坏。但对于大型数据包(MB),Python的字符串实现中会在幕后进行大量复制。
在C语言或类似语言中,环形缓冲区是明显的数据结构,其大小与您期望的最大数据包相同。但是,我没有找到类似的Python实现。我想知道是否有人可以改进我的代码。你如何实现这些类型的服务器?
答案 0 :(得分:1)
首先快速建议:为了清楚起见,您可能希望将packet_size
重命名为msg_len
。您尝试从TCP流解析的是应用程序级协议消息,而不是TCP段(也称为TCP数据包)。
但要解决您的问题:更有效的方法是,当您收到邮件标头时,分配长度为bytearray
的第二个固定大小的msg_len
缓冲区。用它来存储您随后读入的数据。