Резюме: я получаю большие данные изображения по 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) Есть какой-нибудь умный способ сделать это?
Так в общем, как лучше всего это сделать?
Большое спасибо за ваши ответы!