У нас есть инструмент, который используется для удаленного управления серверным процессом через TCP. Одна из функций инструмента - проверить, работает ли сервер, пытаясь подключиться к серверу в цикле в течение заданного периода времени.
Когда мы использовали этот инструмент для проверки того, что сервер не запущен, мы заметили, что точность таймингов в Windows была недостаточной, например попытка подключения в течение 2 секунд к неработающему серверу приведет к тому, что инструмент будет работать в течение 7 секунд, а не ожидаемых 2 секунд, тогда как в Linux время устанавливается с точностью до нескольких миллисекунд. Проблема здесь в том, что мы используем этот инструмент в сценариях запуска, поскольку задержка объявления сервера как мертвого увеличивает время выполнения сценариев запуска.
Оказывается, виноват, кажется, стек Windows TCP / IP: неудачная попытка подключения к локальному порту в Windows занимает от 2 до 5 секунд, в зависимости от машины, тогда как в Linux это происходит почти мгновенно. Теоретически стек Windows не учитывает / не интересуется сообщением об отказе в соединении ICMP, возвращаемым сервером, и продолжает попытку соединения.
Итак, мой вопрос состоит из двух частей: i) кажется ли вышеупомянутая теория правдоподобной, и ii) как я могу сказать Windows, что нужно учитывать ответ ICMP?
- Лаури
Кто-то ответил, что фактический ответ от сервера - это TCP RST, а не ICMP-сообщение, но с тех пор этот ответ был удален.
Во всяком случае, я еще немного покопался и посмотрел на некоторые следы Wireshark неудачных попыток подключения:
i) ответ действительно является TCP RST, ACK, а не ICMP-сообщением, как я изначально думал, что это будет
ii) реализован стек Windows TCP / IP для повторной попытки подключения после RST, ACK в надежде, что сервер мог волшебным образом снова появиться в течение тайм-аута подключения [1]
iii) Администратор может установить для реестра TcpMaxConnectRetransmissions в HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ Tcpip \ Parameters значение ниже, чем значение по умолчанию 3 (WinNT) или 2 (Win2k).
Итак, ответ состоит в том, чтобы настроить реестр и снизить TcpMaxConnectRetransmissions до 0 или 1. Моя единственная проблема с этим «решением» заключается в том, что AFAICT также влияет на попытки подключения, когда исходный SYN удаляется в сети, и в этом случае установка значения на 0 - плохая идея, и установка его на 1 все равно приведет к более продолжительному времени выполнения моих скриптов, чем необходимо.
[1] Для получения дополнительной информации: http://support.microsoft.com/kb/175523
- Лаури