1

(Примечание. Первоначально я задавал этот вопрос на стороне "Сетевой инжиниринг", но модератор отклонил его как "не по теме" и попросил меня задать его здесь.)

Я использую сервер видеонаблюдения под названием ZoneMinder (версия 1.26.5) на Linux Fedora 18. ZoneMinder имеет веб-интерфейс пользователя и использует исполняемый файл CGI с именем "zms" для передачи видеопотока MJPEG в веб-браузер по TCP. Проблема в том, что иногда соединение с видеопотоком не прерывается должным образом; если я просматриваю видеопоток и закрываю окно браузера, основное TCP-соединение остается открытым, а процесс zms на сервере продолжает отправлять видеокадры по сети. Это происходит, даже если я отключаю ВСЕ экземпляры браузера на компьютере с Windows (проверяется с помощью диспетчера задач). Я ожидаю, что Windows должна немедленно завершить TCP-соединение после завершения процесса браузера, но по какой-то неизвестной причине это не всегда происходит, и Windows продолжает принимать пакеты по соединению в течение неопределенного времени. При возникновении этой проблемы процесс zms на сервере все еще видит соединение как открытое и будет продолжать потоковую передачу видео до тех пор, пока машина Windows не будет выключена или процесс zms не будет уничтожен (вручную из командной оболочки). При рассмотрении событий наблюдения нередко накапливается дюжина или более этих "зомби" процессов zms; если я не войду в систему сервера ZoneMinder через SSH и не завершу эти процессы вручную, они будут продолжать работать бесконечно, потребляя пропускную способность дискового и сетевого ввода-вывода и перегружая остальную часть системы.

Находясь в состоянии сбоя, запуск netstat на компьютере с Windows показывает, что TCP-соединение находится в состоянии FIN_WAIT_2. Захват Wireshark показывает, что машина Windows по-прежнему распознает сегменты в соединении, даже если больше нет запущенного процесса, получающего эти данные.

У меня есть 3 машины с Windows: один рабочий стол с Windows 7 Pro SP1, один рабочий стол с Win 7 Home Premium SP1 и один ноутбук с Win 7 Home Premium SP1. Из этих трех, две настольные машины демонстрируют проблему периодически, тогда как ноутбук никогда не демонстрирует проблему.

Я обычно использую браузер Firefox, но я также пробовал Chrome. Оба работают на ноутбуке 100% и периодически выходят из строя на настольных компьютерах. Использование Firefox и Chrome на других опробованных мной платформах, таких как Linux и Android, никогда не вызывает проблемы.

Один из отказавших компьютеров Windows подключен к тому же гигабитному коммутатору, что и серверный блок ZoneMinder; ноутбук Windows, который всегда работает, подключен к точке доступа WiFi и достигает сервера ZoneMinder через второй коммутатор GigE. Устройства Android без проблем подключаются как изнутри, так и снаружи, за брандмауэром.

Чтобы исключить возможность возникновения проблемы с сетевым драйвером, на одном из настольных компьютеров я попытался заменить сетевую карту Realtek на сетевой адаптер Intel, но сбой все равно произошел.

Теперь у меня кончились идеи; как я могу устранить эту проблему дальше? Я могу предоставить снимки Wireshark, если это будет полезно (они большие - ~ 100 МБ - поэтому я их пока остановил).

Спасибо за вашу помощь!

1 ответ1

1

Состояние TCP FIN_WAIT_2 означает, что приложение закрылось, и клиент отправил FIN на сервер. Сервер отправляет ACK и должен сообщить серверу приложений о необходимости завершения работы. Затем он должен отправить FIN клиенту. Ваш клиент ожидает на сервере, чтобы отправить свой FIN.

Ваши машины Windows, демонстрирующие такое поведение, могут использовать разгрузку TCP Chimney, которая выгружает некоторые хозяйственные операции TCP на сетевую карту, например ACKing данных и закрытие соединений. Как только приложение закрывается, NIC берет на себя обработку окончательного закрытия соединения. Это может быть причиной того, что ваш компьютер продолжает получать данные, даже если браузер закрыт.

Вы можете попытаться смягчить проблему, отключив TCP Chimney в Windows. Инструкции здесь.

Однако это не устраняет основную причину того, почему сервер не отправляет FIN. С помощью захвата трафика как на клиенте, так и на сервере вы можете:

  1. Убедитесь, что клиент отправляет FIN
  2. Убедитесь, что сервер получает FIN
  3. Убедитесь, что сервер отправляет FIN
  4. Убедитесь, что клиент получает FIN

Вероятно, в одном из этих шагов есть пробел. Если все шаги выполнены, то проблема в клиенте, и это может быть разгрузкой TCP Chimney.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .