Вопрос или проблема
Если TCP-сервер устанавливает TCP-соединение с TCP-клиентом, и TCP-клиент никогда не отправляет никаких пакетов на сервер.
Я примерно знаю, что файрволы рядом с TCP-сервером могут отправить ему RST. Или есть таймаут keep-alive, который заставляет TCP-соединение завершиться. Но я точно не знаю, что произойдет? Может кто-то немного объяснить?
Возможно ли поддерживать это TCP-соединение, если я не хочу, чтобы оно завершалось?
Я просто надеюсь, что TCP-сервер сможет поддерживать это TCP-соединение в своем TCP-стеке. Но я не хочу, чтобы TCP-клиент был вовлечен. Я не хочу, чтобы он отправлял KEEP-ALIVE. Я не хочу, чтобы какое-либо другое стороннее лицо участвовало. Я просто надеюсь, что, когда я пишу исходный код TCP-сервера, исходный код сможет поддерживать TCP-соединение.
Кроме отправки FIN или RST, единственный способ, чтобы стандартный TCP узнал, что другая сторона отключилась или ушла, — это истечение таймаута.
Это действительно лучшее, что можно сделать по умолчанию, если вы делаете как можно меньше предположений о “другой стороне”, а ваше единственное соединение с этой “другой стороной” — это один сетевой интерфейс.
Событие на более низком уровне модели OSI может привести к тому, что ОС завершит соединение самостоятельно или предоставит информацию, которая может заставить клиента просто сдаться, например, удаление соответствующего сетевого адаптера или изменение состояния канала на “отключено”. Однако это не обязательно происходит.
Общее решение — отправлять периодические сообщения без значимых данных, называемые keepalive, через соединение. TCP это поддерживает, но вы можете сделать это и на уровне приложения.
- FileZilla можно настроить на отправку keepalive-сообщений. Вы можете видеть, как он отправляет команды, которые ничего полезного не делают, но просто выдаются, чтобы “занять” соединение.
- PuTTY, например, имеет опции keepalive.
- Вы также можете установить опции keepalive на сервере, но обычно лучше настроить это на клиенте SSH.
- Многие протоколы маршрутизации отправляют keepalive-сообщения на уровне приложения для проверки работоспособности и доступности других маршрутов, в том числе BGP.
- TCP также поддерживает keepalive-сообщения на уровне протокола, они представляют собой по сути нулевые Ethernet-пакеты, отправляемые с определенным интервалом для проверки соединения. Эта статья tldp.org хорошо объясняет.
Ответ или решение
Поддержка неактивного TCP-соединения может быть сложной задачей, особенно если вы хотите сделать это без взаимодействия с клиентом. В этом ответе я подробно рассмотрю вопросы, связанные с поддержанием неактивного соединения TCP, а также предложу стратегии, которые могут вам пригодиться.
Основные понятия о TCP-соединениях
TCP (Transmission Control Protocol) — это протокол, который используется для установления и управления соединением между клиентом и сервером. Соединение TCP остается активным, пока одна из сторон не отправит FIN (завершение соединения) или RST (сброс соединения), или пока не истечет таймаут неактивности.
Проблемы с неактивными соединениями
При отсутствии активности на стороне клиента (т.е. если клиент никогда не отправляет пакеты на сервер), могут возникнуть следующие проблемы:
-
Таймауты на уровне TCP: TCP использует таймауты для обнаружения разрывов соединения. Если сервер не получает данные в течение установленного времени (обычно от нескольких минут до часов), он может закрыть соединение.
-
Файрволы и NAT: Многие файрволы и устройства NAT могут рассматривать неактивные соединения как ненужные, автоматически сбрасывая их. Это может привести к отправке RST, что завершит соединение.
Способы поддержания TCP-соединения
Если вы хотите сохранить TCP-соединение без участия клиента и третьих сторон, у вас есть несколько подходов:
-
Использование TCP Keep-Alive:
TCP предоставляет механизм keep-alive, который отправляет периодические «пустые» пакеты, чтобы поддерживать соединение. Вы можете настроить параметры keep-alive на уровне операционной системы или в вашем приложении.- Настройка: В Unix-подобных системах параметры TCP keep-alive могут быть настроены с помощью системных команд или через код.
- Пример кода: В некоторых языках программирования, таких как Python, можно использовать параметры
SO_KEEPALIVE
для сокетов.
-
Пользовательские «пинг» сообщения:
Если вы хотите больше контроля, вы можете реализовать на уровне приложения механизм, который периодически отправляет сообщения «пинг» на серверные сокеты. Эти сообщения могут не содержать полезной нагрузки, но они сохранят соединение активным на серверах и маршрутизаторах.- Пример кода: На стороне сервера можно настроить периодическую задачу (например, с использованием cron в Unix) для отправки сообщения на приобретенное соединение.
-
Настройка таймаутов:
Убедитесь, что таймауты вашего TCP-сервера и любые промежуточные устройства установлены на достаточно длительное время, чтобы избежать преждевременной подготовки соединения. Это можно сделать в конфигурации сервера.
Заключение
Обеспечение бессрочного TCP-соединения требует определенных действий и настроек. Вы можете использовать встроенные механизмы TCP, такие как keep-alive, или реализовать пользовательский алгоритм на уровне приложения для поддержки активных соединений. Однако, важно помнить, что все сетевые устройства, участвующие в подключении (как клиент, так и сервер), должны согласовывать эти параметры для достижения наилучших результатов.
Следуя представленной информации, вы сможете поддерживать активное состояние TCP-соединения, даже если клиентская сторона не отправляет данные. Настройте параметры, внимательно изучите возможности вашего стека сетевых протоколов и протестируйте ваше решение, чтобы быть уверенным в его надежности.