Подтвердить что ты не робот

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, если вы просто держите соединение открытым в течение длительного периода времени?

4b9b3361

Ответ 1

Это вроде как:

+-------------------------------------------------------+
|     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. Каждый отправленный байт должен быть учтен, или он будет повторно передан (или соединение reset (закрыто) в тяжелых случаях).

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

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

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

\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/
|                 |                |                    |
|                 | <--- 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, будут иметь определенный протокол для подтверждения данных, отправленных и полученных.

Ответ 2

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.

Ответ 3

Изобразите это: Исходный TCP-стандарт RFC 793 позволял передавать данные с первым пакетом SYN. Однако это не так. Вы получаете отдельный SYN-пакет во время инициирования трехстороннего рукопожатия у запрашивающего соединения. Предположим, что A запрашивает соединение с B, таким образом, A отправляет пакет с установленным битом SYN. B отвечает ACK, чтобы подтвердить получение и отправляет A ACK + SYN-пакеты. Затем данные могут передаваться в дальнейшем.

У Dordal есть очень хорошее объяснение по этому вопросу. Нажмите эту ссылку здесь.