我经常编写简单的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实现。我想知道是否有人可以改进我上面的代码。您如何实现这些类型的服务器?
首先是一个快速建议:为了清楚起见,您可能希望将packet_size
重命名为msg_len
。 您尝试从 TCP 流中解析出的是应用程序级协议消息,而不是 TCP 段(也称为 TCP 数据包)。
但是为了解决您的问题:更有效的方法是,当您收到消息标头时,分配第二个固定bytearray
大小的缓冲区,长度为msg_len
。 使用此选项来存储您随后读入的数据。