Как можно передавать мегабайтные данные через сокет?

Не получается реализовать нормальную буферизацию. Я принимаю данные по 4096 и пока мои данные умещаются в этот промежуток, все работает. Но если данных больше, они как бы "застревают", какие решение могут быть чтобы доставать их в цикле и потом проверить что буфер пуст например. Нашел что-то вроде :

def listen(conn):
    conn.send(command.upper().encode())
    buffer = conn.recv(4096).decode()
    buffering = True
    while buffering:
        if "\n" in buffer:
            (line, buffer) = buffer.split("\n", 1)
            yield line + "\n"
        else:
            more = conn.recv(4096).decode()
            buffer += more
            if not more:
                buffering = False
    if buffer:
        yield buffer


Но для меня это не работает. Как можно передавать мегабайтные данные через сокет?
  • Вопрос задан
  • 450 просмотров
Решения вопроса 1
zvepb
@zvepb Автор вопроса
Для себя нашел способ, ставить тэг в начале и в конце сообщения, например </data>и считывать данные пока не встретится конечный тэг.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Vindicar
@Vindicar
RTFM!
recv() вернёт пустой байт-массив только в одном случае - если другая сторона закрыла соединение на передачу данных (ну или в обе стороны).
Из твоего описания не очень понятно, ожидаешь ли ты закрытия соединения, или какого-то маркера конца сообщения, или вообще сообщения известной длины.
Также, что произойдёт, если передаваемые данные имеют длину ровно 4096 байт?
Если принимаешь данные до конца, то тогда можно упростить код приёма данных до чего-то вида
msg_parts = ""
while True:
  part = conn.recv(4096)
  if part:
    msg_parts += part.decode() #по умолчанию это ascii. 
    #С многобайтными кодировками типа utf-8 могут быть проблемы, 
    #если многобайтный символ будет разбит границей пакета
    while "\n" in msg_parts:
      line, _, msg_parts = msg_parts.partition("\n")
      yield line + "\n" 
  else:
    break
yield msg_parts

Ну или в новом питоне можно еще короче

msg_parts = ""
while part := conn.recv(4096):
  msg_parts += part.decode() #
  while "\n" in msg_parts:
    line, _, msg_parts = msg_parts.partition("\n")
    yield line + "\n" 
yield msg_parts
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы