Проблема с задержками пакетов на TCP / IP Windows 7 loopback adapter (или ошибка в программном обеспечении?)


У нас есть клиентское и серверное приложение, которое в настоящее время тестируется на одной и той же 64-разрядной машине Windows 7. Они оба написаны на C# и используют P/Invoke для вызова библиотек Winsock2.

Приложение работает нормально в целом без каких-либо ошибок. А задержка для каждого "прыжка" по tcp / ip составляет в среднем около 350 микросекунд.

Однако иногда бывают очень длительные задержки от 40 до 50 мс до получения пакетов, а затем внезапно они все прибудут.

Усилия по диагностируйте до сих пор:

  1. Во время этих задержек приема данных сервер продолжает регистрировать, что он отправляет пакеты. Он настроен на отправку тестовых пакетов каждые 1 мс, что он будет делать в течение 15 или 20, а иногда и целых 50 мс, прежде чем клиент получит любой из них.

  2. Tcpdump использовался для обнюхивания пакетов на адаптере loopback и показывает, что в течение этого периода задержки существует трафик от порта сервера (6488) к порту клиента (61743) как обычный.

  3. Клиент вызывает вызов select () winsock2 в цикле, поэтому регистрация через счетчик перед вызовом select () показывает, что он имеет правильный файловый дескриптор. И, конечно, это работает до и после задержки просто отлично.

  4. Дальнейшее ведение журнала сразу после вызова select () показывает, что fd отсутствует-это означает, что чтение в сокете будет заблокировано. Однако во время периодов передачи без каких-либо задержек журнал показывает, что он работает так, как ожидалось. этот select() возвращает fd сокета для выполнения неблокирующего чтения.

Короче говоря, адаптер loopback, кажется, держит эти пакеты где-то в течение длительного времени, прежде чем, наконец, доставить их на принимающую сторону.

Есть еще идеи или решение?

Некоторые мысли таковы, что часто утверждается, что перекрывающийся ввод-вывод работает лучше в Windows, но это, кажется, имеет значение только для масштабируемости, если вам нужно слушать более 64 сокетов.

Может ли быть, что переключение на перекрытие сделает трюк? Мы хотим избежать этого, так как это увеличит сроки выполнения проекта и бюджет. Это должно работать с select() просто отлично.

Кроме того, может ли быть так, что процесс или поток в Windows, который обрабатывает петлю, получает переключение контекста или что-то еще, и если да, то есть ли способ настроить его, чтобы избежать этих задержек?

Edit: правильный ответ должен был гарантировать, что алгоритм Нэгла был отключен. Мы думали, что он был отключен, но вот где была ошибка найдено--в нашей внутренней реализации SetSocketOption () мы использовали GetSocketOption () для проверки. Таким образом, оказывается, что вы должны установить NoDelay до подключения или привязки сокета, иначе он молча не будет иметь никакого эффекта.

Большое спасибо Fun Mun Pieng за правильный ответ!!!

1 2

1 ответ:

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

socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);