Имитировать сетевые условия с C/С++ Socket
Я ищу способ добавить эмуляцию сети в сокет.
Базовым решением будет некоторый способ добавить ограничение пропускной способности для соединения.
Идеальное решение для меня:
- Поддержка расширенных сетевых свойств (латентность, потеря пакетов)
- с открытым исходным кодом
- Имейте похожий API как стандартные сокеты (или обертывания вокруг них)
- Работайте как с Windows, так и с Linux
- Поддержка IPv4 и IPv6
Я видел несколько параметров, которые работают на системном уровне или даже как прокси (Dummynet, WANem, neten и т.д.), но это не сработает для меня, потому что я хочу иметь возможность эмулировать каждый сокет вручную (например, откройте один сокет с эмуляцией модема и один с эмуляцией 3G. В основном я хочу знать, как это делают эти инструменты.
EDIT: Мне нужно встроить эту функцию в свой собственный продукт, поэтому использование дополнительного блока или стороннего инструмента, требующего ручной настройки, неприемлемо. Я хочу написать код, который делает то же самое, что и эти инструменты, и мой вопрос - как это сделать.
Эпилог: Оглядываясь назад, мой вопрос был немного обманчивым. По-видимому, нет никакого способа сделать то, что я хотел непосредственно в сокете. Существует два варианта:
Добавить задержки для отправки/получения (на основе ответа @PaulCoccoli):
добавив задержку перед отправкой и получением, вы можете получить очень грубую симуляцию сети (постоянная задержка для задержки, отправка задержки, чтобы не отправлять больше, чем X байт в секунду, для полосы пропускания).
Пол ответил и прокомментировал мне большое вдохновение, поэтому я награждаю его щедростью.
Добавьте логику моделирования сети в качестве прокси (на основе ответов @m0she и других):
Либо отправьте запрос через прокси, либо используйте прокси для перехвата запросов, а затем добавьте желаемое имитирование. Тем не менее, имеет смысл использовать готовое решение вместо написания собственной реализации прокси - из того, что я видел, Dummynet, вероятно, лучший выбор (это что делает webpagetest.org). Другие варианты приведены в ответах ниже, я также добавлю DonsProxy
Это лучший способ сделать это, поэтому я принимаю этот ответ.
Ответы
Ответ 1
Вы можете скомпилировать прокси-сервер в своем программном обеспечении, которое сделает это.
Это может быть некоторая реализация полноценного прокси-сервера socks (например, this) или, вероятно, лучше, что-то более простое, которое будет служить только вашей цели (и не требует префикса вашего общения с назначение и другие накладные носки).
Этот код может выполняться как отдельный процесс или поток в вашем процессе.
Добавление дросселирования к прокси не должно быть слишком сложным. Вы можете:
- задержка пересылки данных, если она пропускает ограничение по пропускной способности
- добавить задержку, добавив таймер перед операциями чтения/записи на буферах.
- Если вы работаете с протоколом на основе подключения (например, TCP), было бы бессмысленно отбрасывать пакеты, но с протоколом на основе дейтаграммы (UDP) это также было бы просто реализовать.
API создания соединения будет немного отличаться от обычного posix/winsock (если вы не делаете макрос или другую магию), но все остальное (send/recv/select/close/etc..) одинаково.
Ответ 2
Если вы создаете это в своем продукте, вам следует реализовать слой абстракции над API сокетов, чтобы вы могли выбрать свою собственную реализацию во время выполнения. Кроме того, вы можете реализовать оболочки каждой функции сокета и выбрать, следует ли вызывать свою версию или версию системы.
Что касается добавления латентности, вы можете реализовать свою реализацию API сокетов в потоке. В этом потоке имеют приоритетную очередь, упорядоченную по времени (т.е. Этот фоновый поток выполняет очень базовое моделирование дискретных событий). Каждый "пакет", который вы отправляете или получаете, может быть выставлен в очередь вместе со сроком доставки. Каждый срок доставки должен содержать некоторую задержку. Я бы использовал какой-то генератор случайных чисел с гауссовским распределением.
Фоновый поток также должен был имитировать другую сторону соединения, хотя похоже, что вы уже реализовали эту часть?
Ответ 3
Я знаю только Network Link Conditioner для Mac OS X Lion. Вы должны быть разработчиком Mac, чтобы загрузить его, поэтому я не могу установить ссылку загрузки. Только описание от 9to5mac.com: http://9to5mac.com/2011/08/10/new-in-os-x-lion-network-link-conditioner-utility-lets-you-simulate-internet-and-bandwidth-conditions/
Ответ 4
Этот ответ может быть частичным решением для вас при использовании linux:
Имитировать отложенные и отброшенные пакеты в Linux. Он относится к модулю ядра, называемому netem, который может имитировать все виды сетевых проблем.
Если вы хотите работать с TCP-соединениями, "потеря пакетов" может быть проблематичной, поскольку в ядре выполняется большая обработка ошибок (например, восстановление потерянных пакетов). Имитировать это кросс-платформенным способом может быть трудно.
Ответ 5
вы обычно добавляете сетевое устройство в свою сеть, которое дросселирует полосу пропускания или задержки, на основе порта по портам, тогда вы можете достичь того, чего хотите, просто подключившись к порту, выделенному для определенного типа дерьмовой сети, которую вы хотите тест без изменений или модификаций кода.
Простейшие способы сделать это - это добавить правила iptables на сервер Linux, выступающий в качестве прокси.
Если вы хотите, чтобы он работал без отдельного устройства, попробуйте проточку, которая представляет собой программный пакет, который дросселирует вашу сеть на вашем клиентском ПК. (или для Windows)
Ответ 6
Возможно, вы захотите проверить WANem http://wanem.sourceforge.net/. WANEM является Open Source и лицензируется в соответствии с GNU General Public License.
WANem позволяет команде разработчиков приложений настраивать прозрачный шлюз приложений, который может использоваться для имитации характеристик WAN, таких как сетевая задержка, потеря пакетов, повреждение пакетов, отключения, переупорядочение пакетов, джиттер и т.д.
Ответ 7
Если вам требуется только программное решение, которое вы контролируете, вам придется реализовать его самостоятельно. Я не знаю такого существующего пакета.
В то время как слой обертки над сокетом может дать вам возможность ввести задержку, этого будет недостаточно, чтобы ввести потерю или выйти из порядка доставки. Чтобы имитировать эти действия, вам действительно необходимо перехватить данные в пути между двумя стеками TCP.
Подход, который я бы рекомендовал, - использовать туннельное устройство (скажем tunX
). Маршруты должны быть установлены так, чтобы клиент считал, что путь к серверу проходит через tunX
. Дополнительный код (возможно, работающий в другом потоке) будет беспорядочно перехватывать трафик на tunX
и выполнять ваше расширенное поведение перед пересылкой пакетов по истинному физическому интерфейсу, который получит трафик на ваш сервер. Для пакетов, поступающих с сервера на физическом интерфейсе, произойдет обратное. Эти пакеты будут перехватываться кодом клиента, поведенческим дополнением, перед пересылкой через tunX
.
Однако, поскольку вы тестируете клиентское программное обеспечение, я не понимаю, почему вы захотите вставить этот код в свое выпущенное программное обеспечение, если только программное обеспечение не является клиентом, имитирующим WAN.
Ответ 8
Я думаю, вы могли бы использовать такой инструмент, как Сетевой симулятор. Это бесплатно, для Windows.
Единственное, что нужно сделать, это настроить вашу программу на использование правильных портов (и, конечно, настроек для сети).