Кратко

  • PUSH просит TCP не ждать бесконечно новых байтов, прежде чем продвинуть уже переданные данные.
  • PSH не является маркером записи: границы записи, сегмента, буфера приёма и чтения могут не совпадать.
  • Протокол, которому нужны сообщения, должен определить собственное кадрирование поверх TCP.

От «письма» к потоку

В ранних спецификациях TCP рассматривалась идея «письма». RFC 793 объясняет, что этот механизм был переописан как функция PUSH. TCP предоставляет непрерывный поток октетов, а не набор сообщений с сохраняющимися границами.

Запрос PUSH означает просьбу передать уже предоставленные данные и своевременно доставить их удалённому пользователю. Это указание о допустимом ожидании, а не изменение модели данных.

Независимые границы

Согласно RFC 9293, если интерфейс позволяет указать PUSH в SEND, PSH устанавливается в последнем TCP-сегменте, созданном из этого буфера. Но TCP может разделить буфер, объединить данные или сгруппировать последовательные запросы PUSH при формировании сегментов.

Если реализация не предлагает отправителю PUSH, она всё равно не вправе буферизовать данные бесконечно: когда в очереди больше нет данных, на последнем буферизованном сегменте должен стоять PSH.

У получателя буфер может заполниться и быть передан приложению до появления PSH. Сообщать приложению о полученном PUSH необязательно; если интерфейс всё же показывает этот признак, PUSH может привести и к возврату частично заполненного буфера. Размер чтения приложения также не обязан совпадать с размером записи отправителя.

PSH — это намерение продвинуть данные, а не граница записи приложения. Он не гарантирует немедленную передачу, заданное число пакетов или завершение чтения. Ограничения управления потоком, перегрузкой, Nagle и конкретной реализации сохраняются.

Длина, разделители, структуры фиксированного размера или другое правило должны задавать кадрирование приложения. Захват трафика показывает, где PSH появился в одной пакетизации, но сам по себе не восстанавливает достоверные границы записей.

Источники