Получение больших данных по протоколу tcp - является ли socket.MSG_WAITALL напрямую в пустой буфер плохой идеей? - PullRequest
0 голосов
/ 12 января 2019

Резюме: я получаю большие данные изображения по TCP-соединению. Каков наилучший способ поместить его в пустой массив, не занимая слишком много места и не копируя?

Я получаю данные изображения с гиперспектральной камеры (имеющей более 3 длин волн) по протоколу tcp. Камера для меня как бы черный ящик. Я хочу получать данные и иметь их в массивном массиве без чрезмерного копирования данных. Я начал с примеров вокруг (на модуле сокета и на стеке). Но я не был уверен, что это лучший способ, поэтому я хотел использовать массив numpy в качестве буфера. Но для этого мне пришлось использовать socket.MSG_WAITALL, который я нашел на GitHub. (потому что подход 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-Pointer) Есть какой-нибудь умный способ сделать это?

Так в общем, как лучше всего это сделать?

Большое спасибо за ваши ответы!

...