TCP (Transmission Control Protocol, протокол управления передачей) — транспортный протокол, который доставляет данные от программы к программе целиком и в том порядке, в каком их отправили. Перед передачей он устанавливает соединение, нумерует каждый байт, ждёт подтверждения и отправляет заново всё, что потерялось по дороге.
Читается аббревиатура «ти-си-пи». В заголовке IP-пакета у TCP номер 6, у UDP номер 17, оба есть в реестре номеров протоколов IANA. Действующая спецификация протокола описана в RFC 9293 от августа 2022 года: в него собраны все поправки к RFC 793 1981 года. На TCP работают сайты, почта, SSH и большинство баз данных. Где TCP стоит среди других протоколов, мы разбирали в статье о сетевых протоколах простыми словами.
НетологияПрофессия «Сетевой инженер»85 800 ₽12 месяцев
MerionСетевые технологии21 840 ₽2 месяца
ДипломиксУправление и администрирование сетевых устройств информационно-коммуникационных систем10 900 ₽
Академия ТОПУчебная программа “Кибербезопасность и Сетевые технологии”Бесплатно2 года
АПОКСетевой инженер - курс переподготовки32 980 ₽280 часов
GeekBrainsФакультет сетевого инженера145 925 ₽11 месяцев
Что такое TCP простыми словами

Представьте, что вы отправляете книгу по почте, но по одной странице в конверте. Конверты едут разными машинами: часть приходит раньше, часть теряется. TCP работает как служба, которая нумерует конверты, раскладывает страницы на месте по порядку и просит прислать заново потерянные.
Для программы это выглядит как сплошной поток байтов. Браузер пишет запрос в сокет и читает ответ, а как этот ответ резали на куски и сколько раз переотправляли, его не касается. Что такое сокет и как через него открывается соединение, есть в отдельной статье про сокеты.
Что TCP обеспечивает:
- соединение: прежде чем отправить данные, стороны договариваются о начале связи;
- порядок: каждый байт получает порядковый номер, и получатель собирает их правильно;
- подтверждения: получатель сообщает, до какого байта всё дошло;
- повторную отправку: неподтверждённое отправитель шлёт заново;
- управление потоком: быстрый отправитель не заваливает медленного получателя;
- управление перегрузкой: отправитель сбавляет скорость, когда сеть начинает терять пакеты.
TCP работает на транспортном уровне. Ниже него IP, который доставляет пакеты между компьютерами, выше прикладные протоколы вроде HTTP. По модели OSI это четвёртый уровень из семи, подробная раскладка по уровням есть в разборе модели OSI.
| Уровень стека TCP/IP | Что делает | Примеры протоколов |
|---|---|---|
| Прикладной | Смысл данных: страница, письмо, команда | HTTP, SMTP, SSH, DNS |
| Транспортный | Доставка от программы к программе по портам | TCP, UDP |
| Межсетевой | Доставка от компьютера к компьютеру по IP-адресам | IPv4, IPv6, ICMP |
| Канальный | Передача кадров внутри одной сети | Ethernet, Wi-Fi |
Как работает протокол TCP

У каждого TCP-соединения три фазы: установка, передача данных и завершение. Программы видят их как вызовы connect(), send() и close(), а внутри каждая фаза состоит из обмена служебными сегментами.
Установка соединения: тройное рукопожатие
Соединение открывается за три сегмента, поэтому процедуру называют трёхсторонним рукопожатием (three-way handshake). Каждая сторона выбирает свой начальный порядковый номер, ISN, и сообщает его другой.
| Шаг | Кто отправляет | Флаги | Порядковый номер | Номер подтверждения |
|---|---|---|---|---|
| 1 | Клиент | SYN | 1000 | — |
| 2 | Сервер | SYN, ACK | 5000 | 1001 |
| 3 | Клиент | ACK | 1001 | 5001 |
Числа в таблице условные: настоящие ISN выбираются случайно, чтобы постороннему было трудно их угадать. Номер подтверждения всегда на единицу больше чужого ISN, потому что флаг SYN занимает один порядковый номер. После третьего сегмента обе стороны переходят в состояние ESTABLISHED и начинают обмен данными.
Зачем три шага, а не два? Так стороны убеждаются, что слышат друг друга в обе стороны, и отсеивают старые запросы на соединение, застрявшие в сети. Главной причиной спецификация TCP называет именно это: рукопожатие защищает от путаницы со старыми дублями запросов на соединение.
Передача данных и подтверждения
Данные идут сегментами. В каждом указан номер первого байта, а получатель отвечает сегментом с флагом ACK и номером следующего байта, который ждёт. Подтверждение накопительное: ACK с номером 7001 означает «всё до 7000 включительно дошло».
Если подтверждение не пришло за время RTO (retransmission timeout), отправитель повторяет сегмент. RTO подстраивается под измеренное время ответа сети, то есть под пинг, а до первых замеров начать с 1 секунды рекомендует RFC 6298. Пропавший сегмент обнаруживается и раньше таймера: три дублирующих ACK подряд подсказывают отправителю, что получатель видит дыру.
Завершение соединения
Закрывается соединение по частям. Сторона, которой больше нечего отправить, посылает FIN, вторая подтверждает его и может ещё досылать свои данные. Потом вторая сторона отправляет свой FIN и получает ACK.
- Клиент шлёт FIN: «я закончил отправлять».
- Сервер отвечает ACK: «понял».
- Сервер шлёт свой FIN: «я тоже закончил».
- Клиент отвечает ACK и переходит в состояние TIME_WAIT.
TIME_WAIT длится два MSL (Maximum Segment Lifetime, максимальное время жизни сегмента в сети). Пауза нужна, чтобы запоздавшие сегменты старого соединения не попали в новое с теми же портами. В спецификации TCP MSL принят за 2 минуты, а системы ставят своё значение: на macOS команда sysctl net.inet.tcp.msl выводит 15000, то есть 15 секунд.
Есть и аварийный выход, флаг RST. Им сбрасывают соединение без вежливого FIN: так отвечает закрытый порт, так рвёт связь программа, которая упала или решила, что собеседник шлёт ерунду.
Канал основателя Checkroi Вани Буявца3 800 человек читают мой Телеграм-канал про нейросетиСобрал промпты для Claude Code и ChatGPT, разборы ИИ-инструментов и лайфхаки по продвижению бизнеса в одном местеПрисоединитьсяСтруктура TCP-пакета: заголовок и флаги

Единица данных TCP называется сегментом. Сегмент едет по сети внутри IP-пакета, поэтому в разговоре его тоже зовут «TCP-пакетом», и это понятно всем. Сегмент состоит из заголовка и данных, заголовок без опций занимает 20 байт.
| Поле | Размер | Зачем нужно |
|---|---|---|
| Порт источника | 16 бит | Какая программа отправила сегмент |
| Порт назначения | 16 бит | Какой программе он адресован |
| Порядковый номер (Sequence Number) | 32 бита | Номер первого байта данных в сегменте |
| Номер подтверждения (Acknowledgment Number) | 32 бита | Какой байт получатель ждёт следующим |
| Длина заголовка (Data Offset) | 4 бита | Где кончается заголовок и начинаются данные, в 32-битных словах |
| Зарезервировано | 4 бита | Под будущие флаги, сейчас нули |
| Флаги | 8 бит | Служебные отметки: SYN, ACK, FIN и другие |
| Размер окна (Window) | 16 бит | Сколько байт получатель готов принять |
| Контрольная сумма | 16 бит | Проверка, что сегмент не испорчен |
| Указатель срочности | 16 бит | Где кончаются срочные данные, если стоит URG |
| Опции | 0–40 байт | MSS, масштаб окна, метки времени, выборочные подтверждения |
Поле длины заголовка четырёхбитное, максимум 15 слов по 4 байта, поэтому заголовок с опциями не бывает больше 60 байт. Порт занимает 16 бит, отсюда диапазон от 0 до 65535. Какие номера портов за чем закреплены, разобрано в статье о портах компьютера.
Флаги TCP
Флагов восемь, каждый занимает один бит. Список ведёт IANA, а в RFC 9293 перечислены текущие: CWR, ECE, URG, ACK, PSH, RST, SYN и FIN.
| Флаг | Расшифровка | Когда встречается |
|---|---|---|
| SYN | Synchronize | Открытие соединения, первые два сегмента рукопожатия |
| ACK | Acknowledgment | Почти в каждом сегменте после первого |
| FIN | Finish | Сторона закончила отправку |
| RST | Reset | Аварийный сброс, ответ закрытого порта |
| PSH | Push | Просьба сразу отдать данные программе, не копить в буфере |
| URG | Urgent | Есть срочные данные, сейчас почти не используется |
| ECE | ECN-Echo | Получатель сообщает, что роутер пометил перегрузку |
| CWR | Congestion Window Reduced | Отправитель отвечает, что уже сбавил скорость |
Два последних флага добавил RFC 3168 о явном уведомлении о перегрузке, ECN. С ним роутер не выбрасывает пакет при заторе, а помечает его, и TCP снижает скорость без потерь.
MSS и размер окна
MSS (Maximum Segment Size) показывает, сколько байт данных влезает в один сегмент. Стороны сообщают его друг другу опцией в SYN. В обычной сети Ethernet пакет ограничен 1500 байтами, минус 20 байт IP-заголовка и 20 байт TCP-заголовка, получается 1460. Если опции нет, отправитель обязан считать MSS равным 536 байтам для IPv4.
Поле окна шестнадцатибитное, без расширений это максимум 65 535 байт. Для быстрых каналов мало, поэтому есть опция масштаба окна из RFC 7323: значение сдвигается на число бит, указанное при рукопожатии, и окно растёт до 1 ГиБ.
Управление потоком и перегрузкой
Скорость TCP ограничивают два окна, и отправитель смотрит на меньшее из них.
- Окно получателя (rwnd) приходит в каждом сегменте в поле Window. Это место в буфере принимающей программы. Если программа не успевает читать, окно сжимается до нуля, и отправитель ждёт.
- Окно перегрузки (cwnd) отправитель считает сам по тому, как сеть доставляет пакеты. Его никто не передаёт, это оценка пропускной способности пути.
Новое соединение стартует осторожно. По RFC 6928 начальное окно составляет до 10 сегментов, около 14,6 КБ. Дальше идёт медленный старт: с каждым подтверждением окно растёт, за каждый круг примерно вдвое. При первой потере рост переходит в плавный.
Как именно окно растёт и падает, решает алгоритм управления перегрузкой. Самый распространённый из них CUBIC: в RFC 9438 сказано, что его приняли алгоритмом по умолчанию в Linux, Windows и стеках Apple. Проверить на Linux-сервере можно так:
$ sysctl net.ipv4.tcp_congestion_control
net.ipv4.tcp_congestion_control = cubic
Так команда отвечает на Ubuntu. Вместо CUBIC можно включить, например, BBR от Google, если ядро собрано с ним, но для большинства задач менять ничего не нужно.
Чем TCP отличается от UDP
UDP отправляет датаграммы без соединения, без нумерации и без подтверждений. Он быстрее начинает и не ждёт потерянного, зато за порядок и целостность отвечает уже сама программа.
| Свойство | TCP | UDP |
|---|---|---|
| Соединение | Да, тройное рукопожатие | Нет |
| Гарантия доставки | Да, повтор потерянного | Нет |
| Порядок данных | Сохраняется | Не гарантирован |
| Минимальный заголовок | 20 байт | 8 байт |
| Номер протокола в IP | 6 | 17 |
| Где используют | Сайты, почта, SSH, базы данных | DNS-запросы, звонки, игры, видео в реальном времени |
Подробное сравнение, пример UDP-сервера и разбор, почему HTTP/3 ушёл на UDP, есть в статье о протоколе UDP.
Что ходит по TCP и на каких портах это встречается чаще всего:
- HTTP и HTTPS, порты 80 и 443: страницы сайтов. Как устроены запрос и ответ, разобрано в статье о HTTP, а шифрование поверх TCP разобрано в материале про SSL и TLS.
- SSH, порт 22: удалённое управление сервером.
- SMTP, IMAP, POP3: почта, порты и настройки собраны в разборе почтовых протоколов.
- Базы данных: MySQL на порту 3306, PostgreSQL на 5432.
- DNS: обычно UDP 53, но длинные ответы и передача зон идут по TCP 53, подробнее в статье о работе DNS.
Как увидеть TCP-соединение своими глазами
Проще всего поднять сервер и клиента на своём компьютере. Нужен только Python 3, библиотека socket входит в стандартную поставку. Если Python пока в новинку, начните с простых примеров кода для новичков.
Сервер, файл tcp_server.py:
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as srv:
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(("127.0.0.1", 5050))
srv.listen()
print("Жду подключения на порту 5050")
conn, addr = srv.accept()
with conn:
print("Подключился клиент", addr)
data = conn.recv(1024)
print("Получено:", data.decode())
conn.sendall(data.upper())
Клиент, файл tcp_client.py:
import socket
with socket.create_connection(("127.0.0.1", 5050), timeout=5) as sock:
sock.sendall("привет, tcp".encode())
print("Ответ сервера:", sock.recv(1024).decode())
SOCK_STREAM в коде и означает TCP, для UDP был бы SOCK_DGRAM. Запускаем сервер в одном окне терминала, клиента в другом. Вывод сервера:
Жду подключения на порту 5050
Подключился клиент ('127.0.0.1', 59451)
Получено: привет, tcp
Вывод клиента:
Ответ сервера: привет, TCP
Обратите внимание: заглавными стали только латинские буквы. Сервер вызывает upper() у байтов, а не у строки, и такой метод знает только ASCII. TCP доставил байты как есть, а что с ними делать, решает программа.
Рукопожатие прошло внутри create_connection(), завершение при выходе из блоков with. Порт клиента 59451 система выдала сама из временного диапазона. Сразу после обмена посмотрим состояние соединений на macOS:
$ netstat -an -p tcp | grep 5050
tcp4 0 0 127.0.0.1.5050 127.0.0.1.59451 TIME_WAIT
Сервер закрыл соединение первым, поэтому TIME_WAIT остался на его стороне. Через полминуты строка исчезнет.
Чем смотреть соединения в разных системах:
- Linux:
ss -tanпоказывает все TCP-сокеты с состоянием, очередями приёма и отправки, адресами и портами. - macOS:
netstat -an -p tcp, как в примере выше. - Windows:
netstat -an -p TCPв командной строке. - Wireshark показывает сами сегменты с флагами и номерами. Фильтр
tcp.flags.syn == 1оставит только открытия соединений, все поля описаны в справочнике фильтров Wireshark.
Частые ошибки и что с ними делать
За почти любой сетевой ошибкой в логах стоит шаг TCP, который пошёл не так. По тексту ошибки видно, где именно оборвалось.
Connection refused
Попробуем подключиться к порту 5051, где никто не слушает:
import socket
try:
socket.create_connection(("127.0.0.1", 5051), timeout=3)
except ConnectionRefusedError as e:
print("Ошибка:", e)
Ошибка: [Errno 61] Connection refused
Это вывод на macOS, в Linux номер ошибки 111. Компьютер ответил на SYN сегментом RST, то есть машина доступна, но на порту нет программы.
Решение: проверить, что сервис запущен и слушает нужный адрес. Частая ловушка: сервер привязан к 127.0.0.1, а подключаются снаружи. Тогда нужно слушать 0.0.0.0 или конкретный внешний адрес.
Connection timed out
На SYN не пришло ничего. Обычно пакет молча отбрасывает межсетевой экран или адрес недоступен. Linux по умолчанию повторяет SYN 6 раз, это примерно 127 секунд ожидания, так описан параметр tcp_syn_retries в руководстве tcp(7).
Решение: проверить правила файрвола на сервере и по пути, открыт ли порт у хостинга, правильный ли адрес. Если Connection refused приходит мгновенно, а timeout тянется минуту, до машины пакеты идут, но их кто-то фильтрует.
Connection reset by peer
Соединение уже работало, и вдруг пришёл RST. Собеседник упал, перезапустился, закрыл сокет, не дочитав данные, или промежуточный балансировщик оборвал простаивающее соединение. Разбор причин на примере Java есть в статье про ошибку Connection reset.
Address already in use
Сервер перезапустили, а порт занят: на нём висят соединения в TIME_WAIT от прошлого запуска. Решение: опция SO_REUSEADDR перед bind(), она стоит в нашем примере сервера. Если ошибка не уходит, порт держит другой живой процесс: на Linux его покажет ss -ltnp.
Много соединений в CLOSE_WAIT
CLOSE_WAIT значит, что собеседник прислал FIN, а ваша программа так и не вызвала close(). Сеть здесь в порядке, сокеты утекают в коде.
Решение: искать место, где соединение открывается и не закрывается при ошибке. В Python для этого и нужен блок with.
Где освоить сети и TCP/IP системно
Чтобы прочитать заголовок сегмента и понять, откуда взялся TIME_WAIT, хватит этой статьи и одного вечера с Wireshark. Чтобы проектировать сеть, настраивать маршрутизацию и искать, где теряются пакеты между офисами, нужна системная подготовка. Её дают курсы по сетевому администрированию: TCP/IP там проходят вместе с маршрутизацией, VLAN и диагностикой.
TCP на уровне пакетов разбирают в работе системного администратора и сетевого инженера. Ниже курсы, на которых этому учат:
| Курс | Школа | Стоимость со скидкой | В рассрочку | Длительность | Обзор курса от Checkroi |
|---|---|---|---|---|---|
| Администрирование ОС Linux Перейти на сайт курса | 87 595 ₽ | 5556 ₽/мес. | 3 месяца | Обзор курса | |
| Профессия «Сетевой инженер» Перейти на сайт курса | 85 800 ₽ | 3575 ₽/мес. | 12 месяцев | Обзор курса | |
| Сетевые технологии Перейти на сайт курса | 21 840 ₽ | 1578 ₽/мес. | 2 месяца | Обзор курса | |
| Сетевые технологии Huawei Перейти на сайт курса | 11 830 ₽ | 938 ₽/мес. | 2 месяца | Обзор курса | |
| Системное администрирование и информационные технологии - курс переподготовки Перейти на сайт курса | 32 980 ₽ | 2748 ₽/мес. | 576 часов | Обзор курса |
Больше программ — в полном каталоге курсов по сетевому администрированию




