Назад | Перейти на главную страницу

(Почему) FreeBSD 'net.inet.tcp.always_keepalive' нарушает RFC1122?

Работая над серверным приложением, которое работает на FreeBSD и использует TCP, я заметил, что TCP-запросы keepalive отправляются, даже если мое приложение явно отключает SO_KEEPALIVE на TCP-сокетах.

В соответствии с RFC1122, раздел 4.2.3.6 (TCP Keep-Alives):

«Если включены пакеты keep-alive, приложение ДОЛЖНО иметь возможность включать и выключать их для каждого TCP-соединения, и они ДОЛЖНЫ быть отключены по умолчанию».

Я обнаружил, что настраиваемый параметр net.inet.tcp.always_keepalive был включен (установлен в 1), и что его отключение остановит отправку запросов keepalive.

В чем причина включения этого поведения во FreeBSD? Насколько я могу судить, Linux и Windows не имеют такой возможности, но FreeBSD и Mac OS X имеют, поэтому они нарушают RFC.

Чтобы быть более конкретным, при каких обстоятельствах имеет смысл игнорировать пожелания приложения?

В моем случае это простое исправление, поскольку я могу отключить эту опцию, но я хотел бы понять, почему она там есть.

Этот вопрос показывает, что Linux ведет себя согласно RFC.

Обоснование включения функции keep-alive по умолчанию было дано здесь: https://svnweb.freebsd.org/base?view=revision&revision=47752

Добавьте дескриптор для управления глобальными сообщениями поддержки активности TCP и включите их по умолчанию.

Несмотря на их название, он не поддерживает TCP-сеансы, он убивает их, если другой конец ушел в самоволку. Это часто случается с клиентами, которые используют NAT, динамическое назначение IP или имеют верхнюю границу времени безотказной работы 2 ^ 32 * 10 ^ -3 секунды.

Из-за этого не наблюдается заметного увеличения сетевого трафика: два минимальных пакета TCP каждые два часа для активного TCP-соединения.

Многие серверы уже сами поддерживают поддержку активности.

RFC требованиям к хосту уже 10 лет, и он не знает о потерянных клиентах сегодняшнего InterNet.

В любом случае лучше отключить keep-alive, если этого требует приложение, например (в C):

int val = 0;
setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));

но исправить это непросто.

Я думаю, что настраиваемая ручка должна существовать, но, возможно, было бы лучше не использовать ее по умолчанию.

Я рассуждаю так: разработчик приложения может принимать такие решения неправильно, и, в конечном итоге, системный администратор должен контролировать такую ​​сетевую политику, а не разработчик приложения.