python-快速流式传输数据到客户端

python-snappy streaming data in a loop to a client

我想使用 python snappy 将多个压缩数组从服务器发送到客户端,但在第一个数组之后我无法让它工作。这是正在发生的事情的片段: (sock 只是它们通过的网络套接字)

服务器:

for i in range(n): #number of arrays to send
    val = items[i][1] #this is the array
    y = (json.dumps(val)).encode('utf-8') 
    b = io.BytesIO(y)
    #snappy.stream_compress requires a file-like object as input, as far as I know.

    with b as in_file:
        with sock as out_file:
            snappy.stream_compress(in_file, out_file)

客户:

for i in range(n): #same n as before
    data = ''   
    b = io.BytesIO()
    #snappy.stream_decompress requires a file-like object to write o, as far as I know
    snappy.stream_decompress(sock, b)
    data = b.getvalue().decode('utf-8')

    val = json.loads(data)

val = json.loads(data) 仅适用于第一次迭代,但之后它停止工作。当我执行 print(data) 时,只有第一次迭代会打印任何内容。我已经验证服务器确实刷新并发送了所有数据,所以我认为我决定接收数据的方式有问题。

我找不到其他方法来做到这一点。我进行了搜索,唯一能找到的是 ,这让我找到了我目前拥有的东西。

有什么建议或意见吗?

with没有按照你的想法去做,参考一下是documentation。它在块执行后调用 sock.__exit__(),这不是您想要的。

# what you wrote
with b as in_file:
    with sock as out_file:
        snappy.stream_compress(in_file, out_file)

# what you meant
snappy.stream_compress(b, sock)

顺便说一句:

data = '' 已过时,因为它已被重新分配。

添加到@paul-scharnofske 的回答:

同样,在接收方:stream_decompress 直到文件末尾才退出,这意味着它将读取直到套接字关闭。因此,如果您发送单独的多个压缩块,它会在完成之前读取所有这些块,这似乎不是您想要的。最重要的是,您需要在每个块周围添加 "framing" 以便您在接收端知道一个结束和下一个开始的时间。一种方法...对于要发送的每个数组:

  • 像现在一样使用 json 编码的输入创建一个 io.BytesIO 对象
  • 为压缩输出创建一个secondio.BytesIO对象
  • 用两个 BytesIO 对象调用 stream_compress(你可以 write 进入 BytesIO 除了从中读取)
  • 获取输出对象的len
  • 发送编码为 32 位整数的长度,例如 struct.pack("!I", length)
  • 发送输出对象

在接收方,反向处理。对于每个数组:

  • 读取4个字节(长度)
  • 创建一个 BytesIO 对象。准确接收 length 字节,将这些字节写入对象
  • 创建第二个 BytesIO 对象
  • 将接收到的对象作为输入传递,将第二个对象作为输出传递给 stream_decompress
  • json-解码生成的输出对象