При использовании метода recv() иногда мы не можем получать столько данных, сколько хотим, так же, как и с помощью send(). Но мы можем использовать sendall() для решения проблемы отправки данных, как получить данные? Почему такого метода recvall() нет?
Почему в библиотеке сокетов python не включен метод recvall(), например sendall()?
Ответ 1
Нет фундаментальной причины, почему такая функция не может быть предоставлена как часть стандартной библиотеки. Фактически, была хотя бы одна попытка добавить recvall()
.
Учитывая, что его можно легко реализовать как цикл вокруг recv()
, я не думаю, что это серьезное упущение.
Ответ 2
send
содержит дополнительную информацию, которая recv
не содержит: сколько данных необходимо отправить. Если у вас есть 100 байт данных для отправки, sendall
может объективно определить, было ли отправлено менее 100 байт первым вызовом send
, и постоянно отправлять данные до тех пор, пока не будут отправлены все 100 байтов.
Когда вы пытаетесь читать 1024 байта, но возвращаете только 512, у вас нет способа узнать, связано ли это с тем, что остальные 512 байтов задерживаются, и вы должны попытаться прочитать больше, или если читать только 521 байт в первую очередь. Вы никогда не сможете сказать, что будет больше данных для чтения, а рендеринг recvall
бессмыслен. Самое большее, что вы можете сделать, это решить, как долго вы готовы ждать (время ожидания) и сколько раз вы готовы повторить попытку, прежде чем отказаться.
Вы можете задаться вопросом, почему существует очевидная разница между чтением из файла и чтением из сокета. С файлом у вас есть дополнительная информация из файловой системы о том, сколько данных находится в файле, поэтому вы надежно различаете EOF и некоторые другие, которые могут помешать вам просмотреть доступные данные. Нет такого источника метаданных для сокетов.
Ответ 3
Потому что recvall
в корне запутанно: ваше предположение состояло в том, что он читал бы точно-N байтов, но я бы подумал, что он полностью исчерпает поток, основанный на имени.
Операция, которая полностью исчерпывает поток, представляет собой опасный API для множества причин, а двусмысленность в именовании делает этот довольно непроизводительный API.