Глубокое погружение в протокол Linux TCP

ПримечаниеПримечание. Полная ментальная карта доступна по адресу: «DevOps in Linux Mind Map.
Формат заголовка TCP
Давайте сначала посмотрим на формат заголовка TCP. Как видно из этой диаграммы, он намного сложнее, чем UDP.
- Порт источника/назначения: номера портов для источника и получателя. Без этих двух номеров портов мы не знаем, в какое приложение отправлять данные.
- Порядковый номер: это для решения проблемы не по порядку. Если у вас нет хорошего порядкового номера, как вы можете подтвердить, какой из них должен быть первым, а какой позже?
- Номер подтверждения: чтобы подтвердить отправленный пакет и убедиться, что другая сторона его получила.
- Биты состояния. Например, SYN — инициировать соединение, ACK — ответить, RST — переподключиться, FIN — разорвать соединение и т. д. TCP ориентирован на установление соединения, поэтому обе стороны должны поддерживать состояние соединения.
- Размер окна: используется для управления потоком TCP. Обе стороны в общении объявляют окно для определения своих текущих возможностей обработки.
- Контроль перегрузки: для управления скоростью отправки.
Благодаря анализу заголовка TCP мы знаем, что для освоения протокола TCP мы должны сосредоточиться на следующих вопросах:
- Проблема последовательности стабильна и не хаотична;
- Проблема с потерей пакетов, обещают быть надежными;
- Сопровождение соединения от начала и до конца;
- Управление потоком, поймите пропорцию;
- Контроль заторов, знайте, как продвигаться вперед и знайте, как отступать.
Трехстороннее рукопожатие TCP
Теперь давайте посмотрим на установление TCP-соединения. Установление TCP-соединения часто называют трехсторонним рукопожатием.
Процесс рукопожатия можно описать так:
- Клиент вызывает сокет, затем отправляет
SYNиSeqна сервер, и его статус изменяется на состояниеSYN_SEND. - Сервер переходит из состояния
LISTENв состояниеSYN_RECV, затем сервер отправляет обратноSYN+ACK - Клиент получает его, и его состояние меняется на
Established, затем клиент отправляетACKобратно на сервер, сервер получаетACK, и статус становитсяEstablished.
На этом процесс трехэтапного рукопожатия TCP завершен. Если представить весь процесс, то он будет выглядеть так:

(1) Первое рукопожатие: определяет сервер (сервер может получать данные, а клиент может отправлять данные)
(2) Второе рукопожатие: определяет клиент (сервер может получать данные, а сервер может получать данные)
(3) Третье рукопожатие: сервер определяет (клиент может получать данные)
Четыре волны TCP
Поскольку TCP-соединение Duplex,, поэтому каждое направление должно быть закрыто отдельно. Когда сторона завершает свою задачу по передаче данных, она может отправить бит флага завершения FIN, чтобы разорвать соединение в этом направлении, Received a fin означает There is no data flow in this direction. TCP-соединение все еще может отправлять данные после получения FIN. Первая сторона, которая закроется, выполнит Active closure, а другая сторона выполнит Passive closure.

- Первая волна: клиентский процесс отправляет сообщение о разрыве соединения и прекращает отправку данных. Освободите заголовок сообщения данных,
fin = 1, и его порядковый номер будетSEQ = u(равным порядковому номеру последнего байта ранее переданных данных плюс 1). В это время клиент входит в состояниеfin-wait-1. TCP предусматривает, что даже если сегментFINне несет данных, он использует серийный номер. - Вторая волна: сервер получает сообщение о разрыве соединения, отправляет подтверждающее сообщение
ACK = 1, ACK = u + 1и имеет собственный серийный номерSEQ = v. В это время сервер входит в состояниеclose-wait. Сервер TCP также уведомляет высокоуровневый прикладной процесс о том, что направление клиента к серверу освобождается. В это время он находится в полузакрытом состоянии, то есть у клиента нет данных для отправки, но если сервер отправляет данные, клиент все равно должен их принять. Это состояние будет длиться в течение определенного периода времени, то есть продолжительности всего состояния ожидания. После получения запроса на подтверждение от сервера клиент перейдет в статусfin-wait-2и будет ждать, пока сервер отправит сообщение об освобождении соединения (перед этим ему необходимо принять окончательные данные, отправленные сервером). - Третья волна: после отправки окончательных данных сервер отправит сообщение о разрыве соединения клиенту
fin = 1, ACK = u + 1. Поскольку он находится в полузакрытом состоянии, сервер, скорее всего, отправит еще немного данных. Предполагая, что порядковый номер равенSEQ = w, сервер перейдет в состояниеlast-ackи будет ждать подтверждения от клиента. - Четвертая волна: после получения от сервера сообщения о разрыве соединения клиент должен отправить подтверждение
ACK = 1, ACK = w + 1, а его серийный номер —SEQ = u + 1. В это время клиент входит в состояниеtime-wait. Обратите внимание, что в настоящее время TCP-соединение не разорвано. Он должен пройти 2 * MSL (максимальное время жизни сегмента сообщения), прежде чем он перейдет в закрытое состояние, когда клиент отменит соответствующий TCB. Как только сервер получит подтверждение от клиента, он сразу же перейдет в закрытое состояние. Точно так же после отмены TCB соединение TCP завершается. Как видите, сервер завершает TCP-соединение раньше, чем клиент.
Почему три рукопожатия и четыре рукопожатия при закрытии
Потому что, когда сервер получает сообщение с запросом на соединение syn от клиента, он может напрямую отправить сообщение syn + ACK. Сообщение ACK используется для ответа, а сообщение syn используется для синхронизации.
Но при закрытии соединения, когда сервер получает сообщение fin, вполне вероятно, что он не закроет сокет немедленно, поэтому он может только ответить на сообщение ACK и сообщить клиенту: «Я получил сообщение fin, которое вы отправили». Только когда все сообщения на моем сервере отправлены, я могу отправлять сообщения fin, поэтому их нельзя отправлять вместе. Итак, для рукопожатия требуется четыре шага.
Конечный автомат TCP
Сочетание двух временных диаграмм состояния установления и разрыва соединения представляет собой конечный автомат TCP. При обучении рекомендуется сравнивать этот конечный автомат с последовательным конечным автоматом, иначе можно будет легко упасть в обморок.

- LISTEN Ожидание запроса от удаленного приложения TCP
- SYN_SENT Дождитесь подтверждения от удаленной конечной точки после отправки запроса на подключение. Состояние клиента после первого рукопожатия TCP
- SYN-RECEIVED Конечная точка получила запрос на подключение и отправила подтверждение. Конечная точка ожидает окончательного подтверждения. Состояние сервера после второго рукопожатия TCP
- УСТАНОВЛЕНО Указывает, что соединение установлено. Это нормальное состояние фазы передачи данных соединения.
- FIN_WAIT_1 Ожидание подтверждения запроса на завершение соединения или запроса на завершение от удаленного TCP
- FIN_WAIT_2 После того, как эта конечная точка отправит запрос на завершение соединения, дождитесь запроса на завершение соединения от удаленного TCP.
- CLOSE_WAIT Конечная точка получила запрос на закрытие от удаленной конечной точки, и этот TCP ожидает запроса на завершение соединения от локального приложения.
- ЗАКРЫТИЕ Ожидание подтверждения запроса на завершение соединения от удаленного TCP
- LAST_ACK Ожидание подтверждения запроса на завершение соединения, ранее отправленного на удаленный TCP
- TIME_WAIT Подождите достаточное время, чтобы удаленный TCP получил подтверждение своего запроса на завершение соединения.
Заключение
