FIN vs RST в соединениях TCP
Как я понимаю это, есть два способа закрыть TCP-соединение:
- отправить флаг FIN
- отправить флаг RST
RST вызывает немедленное завершение соединения, в то время как в FIN вы получаете подтверждение.
Я понимаю это право, и есть ли другие различия между ними? Могут ли эти два флага использоваться вместе?
Ответы
Ответ 1
-
FIN говорит: "Я закончил говорить с вами, но я все равно буду слушать все, что вы скажете, пока не скажете, что все готово".
-
RST говорит: "Нет разговора, я ничего не скажу, и я не буду слушать ничего, что вы говорите".
RST полезен, если у вас длительное TCP-соединение с небольшим трафиком. Если один из компьютеров перезагружен, он забывает о соединении, а другой компьютер получает RST, как только он отправляет другой пакет.
Ответ 2
Из RFC 1122, который все цитируют, но не цитируют, против меня:
TCP-соединение может заканчиваться двумя способами: (1) обычная последовательность TCP-закрытия с использованием рукопожатия FIN и (2) "прерывание", в котором отправляется один или несколько сегментов RST, и состояние соединения немедленно отбрасывается.
Невозможно использовать оба одновременно. Концепция даже не имеет смысла.
Это возможно с помощью обмана, который я не буду здесь описывать, чтобы закрыть TCP-соединение с RST вместо FIN, но это глупая идея, поэтому я не документирую ее. Во-первых, все отложенные данные в полете теряются.
Ответ 3
FIN или RST будут отправлены в следующем случае
- ваш процесс закрывает сокет
-
ОС выполняет очистку ресурсов, когда ваш процесс выходит без закрытия сокета.
Если ваш вызов процесса close(), FIN будет отправлен со стороны закрытия по умолчанию (обратите внимание: вы можете установить опцию SO_LINGER сокета, чтобы он отправлял RST вместо FIN)
Если ваш процесс завершится без закрытия сокета, ядро закроет соединение tcp и очистит ваш процесс. FIN или RST могут быть отправлены. Если в вашей очереди приема есть данные, RST будет отправлен. В противном случае FIN будет отправлен.
Вы можете прокрутить tcp_close() в tcp.c для получения более подробной информации (я использую kernel-2.6.32-573.7.1 из ветки redhat)