Почему блок recv не блокируется, пока не получит все данные?

Почему системный вызов recv не блокируется до тех пор, пока все данные не будут получены? Каждый раз, когда я видел вызов recv , он находится в цикле while, который только продолжает вызывать recv пока не будут все данные. Почему бы не recv блок recv в первую очередь?

3 Solutions collect form web for “Почему блок recv не блокируется, пока не получит все данные?”

Вы можете запросить блокировку recv до тех пор, пока все данные не будут получены, с флагом MSG_WAITALL . Однако, если сигнал поступает, системный вызов, выполнивший некоторую работу (т. Е. Получение части данных), не может быть автоматически перезапущен для получения остальной информации. Таким образом, даже с MSG_WAITALL бывают случаи, когда вызов recv может возвратиться до заполнения буфера, и вы должны быть готовы обработать эти случаи. Учитывая это, многие люди просто выбирают петлю и не беспокоятся о малоизвестных флагах, таких как MSG_WAITALL .

Что касается того, почему это по умолчанию, есть несколько причин, которые приходят на ум:

  • Часто вы хотите получить частичное чтение. Например, если вы инкрементно отображаете данные по мере их поступления или проксируете их где-то в другом месте, или если данные настолько велики, вы не можете сразу запомнить все это в памяти. В конце концов, если вы просто сразу записываете файл, вам небезразлично, что вы разделили его на 200 записей, а не, скажем, 150?
  • Иногда вы даже не знаете, сколько данных вам нужно в начале. Рассмотрим протокол telnet , который был популярен в то время, когда был разработан API сокетов BSD. Обычно вы будете получать несколько байтов за раз, нет полей длины, сообщающих вам, сколько данных ожидать, и, кроме того, вам нужно сразу отобразить эти данные. Не имеет смысла блокировать, пока вы не заполните буфер здесь. Аналогично линейным протоколам, таким как SMTP или IMAP, вы не знаете, сколько времени команда, пока вы не получили все это.
  • recv часто используется для сокетов датаграмм, где он получает одну дейтаграмму, даже если она намного меньше, чем предоставленный буфер. Естественное расширение потоковых сокетов – это просто вернуть столько, сколько вы можете, не дожидаясь.

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

В большинстве случаев вы не знаете, сколько данных «все данные». Например, если вы получаете данные в линейно-ориентированном протоколе, длина строки может составлять 10 байтов или 65 байтов.

Вы можете изменить флаги сокета на блокировку или неблокирование. Ваш конкретный случай фактически не имеет ничего общего с блокировкой или блокировкой.

Было бы бесполезно, чтобы сетевая функция вела себя так, как вы описываете по умолчанию – что, если поток никогда не заканчивается. Если программа никогда не закончится? Prima facia, это не похоже на здоровое поведение по умолчанию .

Прочтите http://www.scottklement.com/rpg/socktut/nonblocking.html, чтобы ознакомиться с блокировкой и неблокированием ввода-вывода.

  • Каково фактическое воздействие вызова socket.recv с bufsize, который не является силой 2?
  • Соответствие строк: gcc и CPython
  • Доступ к нескольким клавиатурам, введенным C ++ (или python) в Linux
  • Вернуть C ++ в двойное Python?
  • Интеграция консоли Python в приложение GUI C ++
  • Не удалось скомпилировать созданный cython файл .c
  • Обнаруживать, пересекаются ли куб и конус друг с другом?
  • Как подключить программу Python и C?
  • Python - лучший язык программирования в мире.