Контекст:
Обычно двоичный протокол определяет кадров заданного размера. Модуль struct
хорошо разбирает это, при условии, что все было получено в одном буфере.
Проблема:
TCP-сокеты являются потоками. Чтение из сокета не может дать больше байтов, чем запрошено, но может вернуть меньше. Так что этот код не является надежным:
def readnbytes(sock, n):
return sock.recv(n) # can return less than n bytes
Наивный обходной путь:
def readnbytes(sock, n):
buff = b''
while n > 0:
b = sock.recv(n)
buff += b
if len(b) == 0:
raise EOFError # peer socket has received a SH_WR shutdown
n -= len(b)
return buff
может быть неэффективным, потому что если мы запрашиваем большое количество байтов, а данные, если они очень фрагментированы, мы будем многократно перераспределять новый буфер байтов.
Вопрос:
Как можно надежно получить ровно n байтов из сокета потока без риска перераспределения?
Ссылки:
Эти другие вопросы связаны и дают подсказки, но ни один не дает простого и ясного ответа: