如何有效地从socket.recv()解压缩数据?

时间:2014-12-12 17:16:18

标签: python performance sockets buffer slice

我希望通过在调用它之后指定接收大小来优化Python中的套接字接收调用。我收到一个6字节的标题(前4个是空白,最后2个是big-endian)。我的想法是通过解压缩前6个字节获得所需消息的大小,然后使用生成的整数值,将接收缓冲区设置为该特定值,读取套接字并立即将结果添加到我的列表中。这是我的代码段:

engine_messages = []
try:
    while True:
        size_header = struct.unpack('!4cH', self.iosocket.recv(6))[4]
        socket_payload = self.iosocket.recv(size_header)
        engine_messages.append(socket_payload)
except struct.error:
    print 'we received 0 bytes; end of stream'
finally:
    self.iosocket.close()

问题在于,当我进行测试运行时,它会返回RANDOM结果。有时候,我会得到一个包含10个项目的列表,有时是100个,有时是预期值。当我将接收缓冲区设置为4096时,我总是收到正确的回复量。但是这样做,我必须"".join()我的列表并执行昂贵的字符串切片来获取我的行。现在,这对数百/数千的结果集来说并不重要。问题是当我通过"加入时,处理时间开始攀升。数十万或数百万条记录的列表,每行约2500多个字符。

通过直接从流中填充列表,它会增加套接字调用但不会太多,并且可能会大大节省我整个时间。任何想法都将不胜感激。

在Python 2.7.8 / Mac和2.7.8 / Linux上运行

1 个答案:

答案 0 :(得分:1)

这里的问题是你 假设 socket.recv()调用总是读取作为参数给出的字节数。实际上,它可能会读取 less - 然后在等待应用程序消耗的OS网络堆栈缓冲区中可用的任何内容。这有效地破坏了流中协议消息的对齐。

您需要相应地检查应用程序级别的套接字调用和缓冲区返回的大小。

注意:你没有指定,但我在这里假设TCP在异常处理块中提到“stream”。