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, очищаются. Таким образом, весь сегмент не нужно повторно передавать?

2 ответа2

8

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

Из RFC 2018:

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

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

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

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

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

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

3

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

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

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

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

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

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .