Могут ли TCP-пакеты приходить к получателю по частям?
Например, если я отправляю 20 байтов по протоколу TCP, могу ли я быть на 100% уверен, что получу ровно 20 байтов одновременно, а не 10 байтов, тогда еще 10 байтов или около того?
И тот же вопрос для протокола UDP.
Я знаю, что UDP ненадежен, и пакеты не могут прийти вообще или прийти в другом порядке, но как насчет одного пакета? Если он прибудет, могу ли я быть уверен, что это полный пакет, а не кусок?
networking
tcp
udp
iamnp
источник
источник
Ответы:
Да. IP поддерживает фрагментацию, хотя TCP обычно пытается определить MTU пути и сохранить свои пакеты меньшими, чем по соображениям производительности. Фрагментация катастрофически увеличивает скорость потери дейтаграмм. Если путь имеет 10% -ную потерю пакетов, фрагментация дейтаграммы на два пакета делает потерю дейтаграммы почти 20%. (Если какой-либо пакет потерян, датаграмма потеряна.)
Вам не нужно беспокоиться об этом, как и уровень TCP. Уровень IP собирает пакеты в целые дейтаграммы.
Нет, но это не имеет ничего общего с пакетами. По сути, TCP является протоколом потока байтов, который не сохраняет границы сообщений приложения.
То же самое верно и для TCP. Пакеты - это пакеты. Разница в том, что в протоколе TCP есть повторы и переупорядочение, встроенные в протокол, а в протоколе UDP - нет.
Нет, но это не твоя проблема. Протокол UDP обрабатывает повторную сборку дейтаграмм. Это часть его работы. (На самом деле, протокол IP делает это для протокола UDP, поэтому UDP делает это просто путем наложения поверх IP.) Если дейтаграмма разделена на два пакета, протокол IP соберет ее для протокола UDP, поэтому вы увидим полные данные.
источник
Вы не можете быть уверены, что они действительно физически прибывают сразу. Канальные уровни данных ниже TCP / UDP могут разделить ваш пакет, если они захотят. Особенно, если вы отправляете данные через Интернет или любые сети вне вашего контроля, это трудно предсказать.
Но независимо от того, поступают ли данные в одном пакете или нескольких пакетах в приемник. Операционная система должна абстрагировать конкатенацию этих пакетов, поэтому для вашего приложения все равно выглядит, как будто все пришло сразу. Таким образом, если вы не являетесь хакером ядра, в большинстве случаев вам не нужно беспокоиться, если эти данные передаются в одном или нескольких пакетах.
Для UDP ОС также сделает некоторую абстракцию, поэтому приложение, которое получает данные, не должно знать, сколько пакетов было передано. Но отличие от TCP состоит в том, что нет никакой гарантии, что данные действительно поступят. Также возможно, что данные разбиваются на несколько пакетов, и некоторые из них поступают, а некоторые нет. Для принимающего приложения оно все равно выглядит как поток данных, независимо от того, завершено оно или нет.
источник
Примеры. Блоки смежных символов соответствуют вызовам send ():
TCP:
Все отправленные данные принимаются по порядку, но не обязательно в тех же порциях.
UDP:
Данные не обязательно находятся в том же порядке и совсем не обязательно принимаются, но сообщения сохраняются во всей их полноте.
источник
Нет, TCP - это потоковый протокол, он хранит данные в порядке, но не группирует их по сообщениям. С другой стороны, UDP ориентирован на сообщения, но ненадежен. SCTP имеет лучшее из обоих миров, но его нельзя использовать изначально, потому что NAT ломают интернет.
источник
Существует некоторая уверенность в том, что если вы отправите 20 байтов в самом начале потока TCP, он не будет получен как две 10-байтовые части. Это связано с тем, что стек TCP не будет отправлять такие маленькие сегменты: минимальный размер MTU. Однако, если отправка находится где-нибудь в середине потока, все ставки выключены. Возможно, ваш стек протоколов занимает 10 байт данных для заполнения сегмента и отправки его, а затем следующие десять байтов переходят в другой сегмент.
Ваш стек протоколов разбивает данные на куски и помещает их в очередь. Размеры чанка основаны на MTU пути. Если вы выполняете операцию отправки, и данные в очереди все еще находятся в ожидании, стек протоколов обычно просматривает сегмент, находящийся в хвосте очереди, и видит, есть ли место в этом сегменте для добавления дополнительных данных. Комната может быть размером всего в один байт, поэтому даже двухбайтовую передачу можно разбить на две части.
С другой стороны, сегментация данных означает, что возможны частичные чтения. Операция приема может потенциально активироваться и получать данные, когда приходит всего один сегмент. В широко реализованном API сокетов для вызова приема может запрашиваться 20 байтов, но он может возвращаться с 10. Конечно, на нем может быть построен уровень буферизации, который будет блокироваться до получения 20 байтов или до разрыва соединения. В мире POSIX этот API может быть стандартным потоком ввода-вывода: вы можете
fdopen
использовать дескриптор сокета для полученияFILE *
потока и использоватьfread
его для заполнения буфера таким образом, чтобы полный запрос удовлетворял столькоread
вызовов, сколько требуется ,UDP датаграммы формируют данные. Каждый отправляющий вызов генерирует дейтаграмму (но о пробке см. Ниже). Другая сторона получает полную дейтаграмму (и в API сокетов она должна указывать достаточно большой буфер для ее хранения, иначе дейтаграмма будет обрезана). Большие дейтаграммы фрагментируются IP-фрагментацией и прозрачно собираются для приложений. Если какой-либо фрагмент отсутствует, вся дейтаграмма теряется; в этой ситуации невозможно прочитать частичные данные.
Существуют расширения интерфейса, позволяющие нескольким операциям указывать одну дейтаграмму. В Linux сокет может быть «закупорен» (запрещен для отправки). Пока они укупорены, записанные данные собираются в единый блок. Затем, когда сокет «откупорен», можно отправить одну дейтаграмму.
источник