Я предлагаю вам сначала отправить длину, а затем данные.
Когда сервер получает длину "полезной нагрузки", он знает, сколько байтов данных ожидает.
Клиент:
- отправить
len(f)
как 8
байт - отправить данные
f
Сервер:
- получить
8
байтов для получения len_f
. - для получения
len_f
байтов данных.
Нет необходимости получать данные в виде блоков по 1024 байта.
В моем примере len_f
кодируется в формате base64
.
Количество байтов для отправки len_f
всегда составляет 8 байтов (из-за заполнения base64 c padding) ,
Вы также можете закодировать data
как base64
.
Важно, если вы отправляете данные через HTTP.
Я поставил base64
кодирование / декодирование данных изображения в комментарии.
Только длина кодируется как base64
(вы также можете отправить длину в текстовом формате).
Клиент:
import socket
import numpy as np
import cv2
import base64
s = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
s.connect(("127.0.0.1", 60124))
width, height, n_frames = 640, 480, 100 # 100 frames, resolution 640x480
for i in range(n_frames):
# Generate synthetic image:
img = np.full((height, width, 3), 60, np.uint8)
cv2.putText(img, str(i+1), (width//2-100*len(str(i+1)), height//2+100), cv2.FONT_HERSHEY_DUPLEX, 10, (30, 255, 30), 20) # Green number
# JPEG Encode img into f
_, f = cv2.imencode('.JPEG', img)
# Encode jpeg_img to base64 format
#f = base64.b64encode(f)
# Get length of f and encode to base64
#f_len = base64.b64encode((len(f)).to_bytes(4, byteorder='little'))
f_len = base64.b64encode((len(f)).to_bytes(4, byteorder='little'))
# Send the length first - so the server knows how many bytes to expect.
s.sendall(f_len) # Send 8 bytes (assumption: b64encode of 4 bytes will be 8 bytes due to the automatic padding feature).
s.sendall(f)
s.close()
Сервер:
import socket
import numpy as np
import cv2
import base64
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("127.0.0.1", 60124))
s.listen(5)
c, a = s.accept()
while True:
# Read 8 bytes that tells the length of encoded image to be expected.
data = c.recv(8)
if len(data) != 8:
break
# Decode f_len from base64
f_len = base64.decodebytes(data)
# Convet from array of 4 bytes to integer value.
f_len = int.from_bytes(f_len, byteorder='little')
#f = c.recv(1024)
# Receive the encoded image.
data = c.recv(f_len)
if len(data) != f_len:
break
#x = base64.decodebytes(data) # Decode base64
#x = np.fromstring(x , np.uint8)
x = np.fromstring(data, np.uint8)
var = cv2.imdecode(x, cv2.IMREAD_COLOR)
if var is None:
print('Invalid image')
else:
cv2.imshow("Camera" , var)
cv2.waitKey(100)
s.close()
cv2.destroyAllWindows()