В чем разница между Убийством с ОЖИДАНИЕМ ВРЕМЕНИ и SO_REUSEADDR

StackOverflow https://stackoverflow.com/questions/587961

  •  06-09-2019
  •  | 
  •  

Вопрос

Я читал об использовании опции сокета SO_LINGER для преднамеренного "уничтожения" состояния ожидания, установив время задержки равным нулю.Затем автор книги продолжает говорить, что мы никогда не должны этого делать и вообще, что мы никогда не должны вмешиваться в состояние ожидания.Затем он немедленно рекомендует использовать опцию SO_REUSEADDR, чтобы обойти состояние ожидания по времени.

Мой вопрос в том, в чем разница?В обоих случаях вы преждевременно завершаете состояние ожидания по времени и рискуете получить повторяющиеся сегменты.Почему одно хорошее, а другое плохое?

Это было полезно?

Решение 2

Я еще немного почитал, и это мое понимание того, что происходит (надеюсь, правильное):

Когда вы вызываете close в сокете, для которого установлен SO_REUSEADDR ( или ваше приложение выходит из строя), происходит следующая последовательность:

  1. TCP Отправляет все оставшиеся данные в буфере отправки и FIN
  2. Если было вызвано close, оно возвращается немедленно, не указывая, были ли успешно доставлены какие-либо оставшиеся данные.
  3. Если данные были отправлены одноранговый узел отправляет подтверждение данных
  4. Одноранговый узел отправляет подтверждение FIN и отправляет свой собственный пакет FIN
  5. FIN однорангового узла подтвержден, и ресурсы сокета освобождены.
  6. Сокет не вводит ВРЕМЯ -ПОДОЖДИТЕ.

Когда вы закрываете сокет со временем SO_LINGER, установленным на ноль:

  1. TCP отбрасывает все данные в буфере отправки
  2. TCP отправляет ПЕРВЫЙ пакет одноранговому узлу
  3. Ресурс сокета освобожден.
  4. Сокет не вводит ВРЕМЯ -ПОДОЖДИТЕ

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

Другие советы

TIME_WAIT - это абсолютно нормально.Это происходит после TCP FIN на локальной стороне, за которым следует подтверждение TCP FIN из удаленного местоположения.В режиме TIME_WAIT вы просто ждете, когда любые случайные пакеты прибудут на локальный адрес.Однако, если есть потерянный или случайный пакет, то TIME_WAIT гарантирует, что TTL или "время жизни" истекает, прежде чем использовать адрес снова.

Если вы используете SO_REUSEADDR, то вы, по сути, говорите: "Я предполагаю, что случайных пакетов нет".Что становится все более вероятным в современных, надежных сетях TCP.Хотя это все еще возможно, но маловероятно.

Установка значения SO_LINGER равным нулю приводит к инициированию аварийного закрытия, также называемого "прерыванием соединения". Здесь вы не учитываете TIME_WAIT и игнорируете возможность случайного пакета.

Если вы видите FIN_WAIT_1, то это может вызвать проблемы, так как удаленное местоположение не отправило подтверждение TCP FIN в ответ на ваш FIN.Таким образом, процесс был либо остановлен, либо подтверждение TCP FIN было потеряно из-за сетевого раздела или неправильного маршрута.

Когда вы видите CLOSE_WAIT, у вас проблема, здесь происходит утечка соединений, поскольку вы не отправляете подтверждение TCP FIN при задании TCP FIN.

Я использую SO_REUSEADDR для привязки подстановочного знака () к локальному порту, к которому у какой-то другой программы уже было открыто соединение.Оказывается, это конкретное использование никогда не вызовет проблем до тех пор, пока никакие два сокета не попытаются одновременно прослушать () одну и ту же комбинацию addr / port.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top