Отправляет ли TCP SYN / ACK для каждого пакета или только при первом подключении?

У меня есть TCP-сервер, который прослушивает входящего клиента, а затем отправляет ему один пакет данных каждую секунду. Мне было интересно, пакет SYN / ACK отправляется только при начальном подключении, поэтому он выглядит так:

<client connect>
SYN
ACK
DATA
DATA
DATA
<client disconnect>

Или он отправляется с каждым пакетом, как это?

<client connect>
SYN
ACK
DATA

SYN
ACK
DATA

SYN
ACK
DATA
<client disconnect>

Также, если это первый случай, есть ли преимущества UDP над TCP, если вы просто поддерживаете соединение открытым в течение длительного периода времени?

41
задан Daniel T. 30 August 2010 в 21:47
поделиться

2 ответа

Это примерно так:

+-------------------------------------------------------+
|     client           network            server        |
+-----------------+                +--------------------|
|    (connect)    | ---- SYN ----> |                    |
|                 | <-- SYN,ACK -- |     (accepted)     |
|   (connected)   | ---- ACK ----> |                    |
\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/

when client sends...
\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/
|                 |                |                    |
|     (send)      | ---- data ---> |                    |
|                 | <---- ACK ---- |  (data received)   |
\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/

when server sends...
\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/
|                 |                |                    |
|                 | <--- data ---- |       (send)       |
| (data received) | ---- ACK ----> |                    |
\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/

...and so on, til the connection is shut down or reset

SYN запускает соединение; обычно вы видите его только тогда, когда соединение устанавливается. Но все данные, отправляемые через TCP, требуют подтверждения. Каждый отправленный байт должен учитываться, иначе он будет передан повторно (или сброс соединения (закрытие), в тяжелых случаях).

Фактические соединения обычно не совсем такие, как на диаграмме выше, по двум причинам:

  • ACK могут накапливаться, поэтому один ACK может подтверждать все, что было получено до этого момента. Это означает, что вы можете подтвердить две или более отправки одним ACK.
  • ACK — это просто флаг и поле в заголовке TCP. Для его отправки требуется, по крайней мере, пропускная способность, равная заголовку, плюс все, что прикрепляется к нижним уровням. Но сегменты данных уже включают все это...поэтому, если вы отправляете данные, вы можете одновременно отправить ACK бесплатно.

Большинство стеков TCP/IP пытаются уменьшить количество «чистых» ACK без чрезмерного риска повторной передачи или сброса соединения. Так что такой разговор вполне возможен:

\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/
|                 |                |                    |
|                 | <--- data ---- |       (send)       |
| (data received) |                |                    |
|     (send)      | -- data,ACK -> |                    |
|                 |                |  (data received)   |
|                 | <- data,ACK -- |       (send)       |
| (data received) |                |                    |
|  (wait a bit)   | <--- data ---- |       (send)       |
| (data received) |                |                    |
|     (send)      | -- data,ACK -> |                    |
|                 |                |  (data received)   |
|     (send)      | ---- data ---> |   (wait a bit)     |
|                 |                |  (data received)   |
|                 | <- data,ACK -- |       (send)       |
| (data received) |                |                    |
|  (wait a bit)   |   (dead air)   |                    |
|                 | ---- ACK ----> |                    |
\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/

Что касается UDP, то здесь нет встроенной концепции SYN и ACK — UDP по своей природе «ненадежен» и не ориентирован на соединение, поэтому эти концепции не применяются. столько. Ваше подтверждение обычно будет просто ответом сервера. Но некоторые протоколы прикладного уровня, построенные поверх UDP, будут иметь какой-то специфический для протокола способ подтверждения отправленных и полученных данных.

84
ответ дан 27 November 2019 в 00:23
поделиться

SYN только в начале.

ACK передается на последующие сегменты в любом направлении. ACK также определяет размер окна. Например, если размер окна равен 100, отправитель может отправить 100 сегментов, прежде чем он ожидает получить ACK. Например, если отправитель отправляет 100 сегментов, но сегмент номер 50 потерян, получатель получит 1-49 и 51-100. Затем получатель подтвердит ACK для 50 (следующий сегмент, который он ожидает) и установит размер окна равным 1. Отправитель повторно отправит 1 сегмент с порядковым номером 50. Затем получатель подтвердит ACK для 101 и снова установит размер окна на более высокое число.

Оба фактически являются полями в заголовке TCP и могут быть отправлены с данными, хотя SYN и первый ACK обычно не содержат данных.

Таким образом, ни один из описанных вами сценариев не совсем верен. Первый на самом деле ближе к реальности, но все пакеты данных после SYN должны включать ACK, а также поле номера подтверждения, которое идентифицирует номер следующего ожидаемого пакета.

Окончание сеанса также включает рукопожатия с пакетами, помеченными FIN, и относящиеся к ним ACK.

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

Кроме того, если это первый случай, есть ли какие-либо преимущества UDP по сравнению с TCP, если вы просто держите соединение открытым в течение длительного периода времени?

С помощью UDP вы не можете просто держать соединение открытым в течение длительного периода времени. Нет подключения.

Эта последовательность флагов SYN/ACK/FIN создает соединение.

При использовании UDP отсутствуют SYN или ACK, поэтому связь является односторонней, доставка не гарантируется, а порядок не сохраняется. Но у него меньше накладных расходов, поэтому он полезен, когда скорость важнее надежности, как, например, в потоковом мультимедиа.

Это еще немного упрощено, но это лучшее, что я могу сделать на данный момент.

Более подробная информация об этом содержится в статьи Википедии о TCP и, конечно же, в RFC.

12
ответ дан 27 November 2019 в 00:23
поделиться