Существует некоторая уверенность в том, что если вы отправите 20 байтов в самом начале потока TCP, он не будет получен как две 10-байтовые части. Это связано с тем, что стек TCP не будет отправлять такие маленькие сегменты: минимальный размер MTU. Однако, если отправка находится где-нибудь в середине потока, все ставки выключены. Возможно, ваш стек протоколов занимает 10 байт данных для заполнения сегмента и отправки его, а затем следующие десять байтов переходят в другой сегмент.
Ваш стек протоколов разбивает данные на куски и помещает их в очередь. Размеры чанка основаны на MTU пути. Если вы выполняете операцию отправки, и данные в очереди все еще находятся в ожидании, стек протоколов обычно просматривает сегмент, находящийся в хвосте очереди, и видит, есть ли место в этом сегменте для добавления дополнительных данных. Комната может быть размером всего в один байт, поэтому даже двухбайтовую передачу можно разбить на две части.
С другой стороны, сегментация данных означает, что возможны частичные чтения. Операция приема может потенциально активироваться и получать данные, когда приходит всего один сегмент. В широко реализованном API сокетов для вызова приема может запрашиваться 20 байтов, но он может возвращаться с 10. Конечно, на нем может быть построен уровень буферизации, который будет блокироваться до получения 20 байтов или до разрыва соединения. В мире POSIX этот API может быть стандартным потоком ввода-вывода: вы можете fdopen
использовать дескриптор сокета для получения FILE *
потока и использовать fread
его для заполнения буфера таким образом, чтобы полный запрос удовлетворял столько read
вызовов, сколько требуется ,
UDP датаграммы формируют данные. Каждый отправляющий вызов генерирует дейтаграмму (но о пробке см. Ниже). Другая сторона получает полную дейтаграмму (и в API сокетов она должна указывать достаточно большой буфер для ее хранения, иначе дейтаграмма будет обрезана). Большие дейтаграммы фрагментируются IP-фрагментацией и прозрачно собираются для приложений. Если какой-либо фрагмент отсутствует, вся дейтаграмма теряется; в этой ситуации невозможно прочитать частичные данные.
Существуют расширения интерфейса, позволяющие нескольким операциям указывать одну дейтаграмму. В Linux сокет может быть «закупорен» (запрещен для отправки). Пока они укупорены, записанные данные собираются в единый блок. Затем, когда сокет «откупорен», можно отправить одну дейтаграмму.