если TCP-пакет получил частичное подтверждение, как отреагирует механизм повторной передачи?


12

если клиент tcp отправляет пакет с порядковым номером от 10000 до 20000 на сервер tcp. TCP отвечает ACK с seq_ack 20001.

если я перехватываю пакет TCP от клиента и делю пакет на 2 сегмента tcp, один с seq от 10000 до 15000, а другой с seq от 15001 до 20000. И затем эти 2 сегмента TCP отправляются на сервер TCP. Предположим, что второй сегмент потерян в пути. TCP-сервер ответит ACK с помощью seq_ack 15001.

Теперь, когда TCP-клиент отправляет целостный пакет с последовательностями от 10000 до 20000, но он получает ACK с 15001, с точки зрения клиента, это странно. Как это отреагирует? Теоретически, клиент должен повторно передать байты с seq 15001 до 20000, а именно, клиент будет передавать новые пакеты с seq 15001. Но как насчет практики, в реализации стека TCP, она такая же, как в теории?

Я думаю, что в буфере отправки TCP, когда сегмент TCP отправляется, сегмент все еще остается там до ACK. Когда приходит ACK, эти байты для сегмента очищаются из буфера. В буфере отправки есть указатель, когда приходит ACK, указатель указывает на местоположение, которому соответствует ack_seq. Байты, которые находятся ниже ack_seq, очищаются. Таким образом, весь сегмент не должен быть передан повторно?

Ответы:


8

Это называется выборочным подтверждением и уже включено в спецификацию TCP, определенную в RFC 2018 . Это позволило бы клиенту действительно пересылать только байты с 15001 по 20000 (поскольку они находятся в разных пакетах / сегментах, если вы их разделили, как вы говорите), но, что более интересно, он даже допускает неупорядоченные подтверждения.

Из RFC 2018:

При получении ACK, содержащего опцию SACK, отправитель данных ДОЛЖЕН записать выборочное подтверждение для будущей ссылки. Предполагается, что отправитель данных имеет очередь повторной передачи, которая содержит сегменты, которые были переданы, но еще не подтверждены, в порядке порядкового номера.

Поддержка SACKбудет не требуется спецификацией TCP. Если клиент или сервер не поддерживают выборочное подтверждение, все байты с 10000 по 20000 действительно должны быть переданы повторно.

В реализации стека TCP это так же, как в теории?

Обычно SACK это поддерживается, как производительность, эффективность и латентность выгода значительна - особенно в сети , как Интернет.

Однако в действительности эти предположения должны выполняться, даже если вы вручную управляете пакетами, как вы заявили. В соответствии с RFC 793 , как минимум, все окна данные должны быть повторно переданы, но приемник действительно знает , что данные получили, по крайней мере в силе . Для деталей реализации, Раздел 3.3 - Порядковые номера из RFC 793.

Для ознакомления с общей схемой всего процесса как с поддержкой выборочного подтверждения, так и без нее см. Эту статью (которая включает в себя несколько очень полезных диаграмм).


это немного странно для меня, потому что TCP является потоковым, байтовым протоколом. Почему он должен ретранслировать весь сегмент? Мне кажется, что TCP без SAKC является сегментно-ориентированным потоковым протоколом, но TCP с Sack реально ориентирован на байты. Я думаю, что RFC специально не уточняет это.
misteryes

как стек TCP управляет своим буфером отправки, это то же самое, что я написал в обновленном вопросе.
Misteryes

@misteryes эта статья описывает процесс (с некоторыми отличными диаграммами тоже!).
Прорыв

В рекомендованной вами ссылке кажется, что автор все еще обсуждает проблему сегментно-ориентированным способом, а не байтово-ориентированным способом. Не так ли?
misteryes

1
Я знал SACK прежде, чем я отправлю этот вопрос. В самом начале я не думаю, что SACK как-то связан с этим вопросом. На мой взгляд, если TCP не байтово-ориентированный, а сегментно-ориентированный, то SACK также должен быть таким же. Разница между SACK-включенным и SACK-отключенным состоит в том, что с SACK TCP допускает дыру в последовательности в ack_seq. Но я думал, что отверстие последовательности соответствует сегменту. в то время как по вашему высказыванию, отверстие может быть половиной / частью сегмента.
Misteryes

3

Размеры сегментов могут (и могут) изменяться в течение срока жизни соединения. К счастью, TCP не нужно записывать размер сегмента, с которым отдельные пакеты были отправлены ранее. Поэтому он будет делать следующее:

  1. Всякий раз, когда приходит ACK, перемещайте указатель на первый неподтвержденный байт соответственно и отбрасывайте любой ненужный сейчас буфер.
  2. Когда возникает необходимость в повторной передаче (Быстрая повторная передача или Тайм-аут; НЕ сразу после получения первого ACK!), Он будет повторно отправлен в текущем действительном размере сегмента, начиная с указателя на первый неподтвержденный байт.

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

Позвольте мне дать некоторые пояснения, чтобы объяснить:

TCP использует байты или сегменты? Для приложения TCP предоставляет интерфейс потока байтов. Кроме того, все поля заголовка и внутренние переменные в байтах. Однако для передачи информации TCP разбивает их на сегменты, так как посылка байтов по одному была бы довольно бесполезной :-). Повсеместное использование счетчиков байтов имеет то преимущество, что размер сегмента не должен оставаться постоянным в течение всего времени жизни соединения:

  • Вводятся опции, например, переключение SACK при повторной передаче (реальные реализации будут сталкиваться с этим редко, если вообще будут)
  • MTU пути изменяется, например, одна ссылка на пути изменяется на более низкую MTU, или поднимается узкое место MTU. Это происходит, когда устанавливаются туннели (VPN, PPPoE) или протокол маршрутизации выбирает другой канал MTU. Это происходит в IPv4 с набором «Не фрагментировать» (верно для большинства современных TCP); всегда в TCPv6).

КСТАТИ: SACK не является ответом здесь, так как получатель (как правило) будет использовать SACK, только если он распознает дыру в байтовом потоке (то есть, если пакет потерян, но пришел следующий пакет).

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.