首页 > 解决方案 > 通过 tcp 接收大数据 - socket.MSG_WAITALL 直接进入 numpy 缓冲区是个坏主意吗?

问题描述

摘要:我通过 tcp 连接接收大图像数据。在不使用太多空间和复制的情况下将其放入 numpy 数组的最佳方法是什么?

我正在通过 tcp 从高光谱相机(具有超过 3 个波段)获取图像数据。相机对我来说就像一个黑匣子。我想接收数据并将其放在一个 numpy 数组中,而无需复制太多数据。我从周围的例子开始(在套接字模块和stackoverflow上)。但我不确定这是否是最好的方法,所以我想使用一个 numpy 数组作为缓冲区。但因此我不得不使用我在 GitHub 上找到的 socket.MSG_WAITALL。(因为方法 3 - 见下文 - 不起作用)但它很少使用,也没有示例,我了解了 TCP 以不可预测的块发送。所以我想知道这背后是什么,为什么不应该使用它(或者应该使用它?),总的来说,你认为实现这一目标的最佳方法是什么。

所以这是我的 3 次尝试(1 次和 2 次都运行良好并且几乎同时运行):

import socket
import numpy as np
def receiveImage1(self):
    #typical example - should have best performance they said
    MSGLEN = 480 * 252 * 640

    chunks = []
    bytes_recd = 0
    while bytes_recd < MSGLEN:
        chunk = self.connection.recv(min(MSGLEN - bytes_recd, 2048))
        bytes_recd = bytes_recd + len(chunk)
        chunks.append(chunk)

    #is this a copy?
    b = b''.join(chunks)
    n = np.frombuffer(b, np.dtype('<H')).reshape((480,252,320))
    return n

def receiveImage2(self):
    #create buffer and write into it
    MSGLEN = 480 * 252 * 640
    npbuffer = np.ones((480, 252, 320), np.dtype('<H'))

    self.connection.recv_into(npbuffer, MSGLEN, socket.MSG_WAITALL)

    return npbuffer

def receiveImage3(self):
    #create buffer and write into it in chunks (not working)
    MSGLEN = 480 * 252 * 640
    npbuffer = np.ones((480, 252, 320), np.dtype('<H'))

    bytes_recd = 0
    while bytes_recd < MSGLEN:
        lgt = self.connection.recv_into(npbuffer,min(MSGLEN - bytes_recd, 2048))
        bytes_recd = bytes_recd + lgt
    return npbuffer

所以 1 和 2 几乎同时运行。我想知道优点和缺点以及使用的副本和空间。你更喜欢什么?

尝试 3 时,我认为指向缓冲区的指针将随写入一起进行,因此它将填满整个缓冲区。(当然不是,而是一遍又一遍地覆盖第一个字节)所以我试图找到一种方法给缓冲区一些偏移量或其他东西,但我找不到它。(我希望有一些行为,比如一个 C 指针)有什么聪明的方法可以做到这一点吗?

那么总的来说,最好的方法是什么?

非常感谢您的回答!

标签: arraysnumpysocketstcpbuffer

解决方案


推荐阅读