Искусственное создание ошибки тайм-аута соединения


291

В нашем программном обеспечении произошла ошибка, возникающая при получении тайм-аута соединения. Эти ошибки очень редки (обычно, когда моя связь прерывается нашей внутренней сетью). Как я могу создать такой эффект искусственно, чтобы я мог протестировать наше программное обеспечение?

Если это имеет значение, приложение написано на C ++ / MFC с использованием классов CAsyncSocket.

Редактировать:

Я попытался использовать несуществующий хост, и я получаю ошибку сокета:

WSAEINVAL (10022) Неверный аргумент

Моей следующей попыткой было использовать предложение Александра подключиться к другому порту, например 81 (хотя на моем собственном сервере). Это сработало отлично. Точно так же, как потерянное соединение (ожидание 60 секунд, затем ошибка). Спасибо!


Привет Марк, я попробовал решение, которое работает для тебя, но я получаю # 503 (Сервис недоступен). Не должно быть одним из них, # 504 (Тайм-аут шлюза), # 599 (Ошибка тайм-аута сетевого подключения), # 598 (Ошибка тайм-аута сетевого чтения).
CoDe

Ответы:


297

Подключитесь к существующему хосту, но к порту, заблокированному межсетевым экраном, который просто отбрасывает пакеты TCP SYN. Например, www.google.com:81.


6
Этот ответ прост и работает так же, как ответ @ emu ниже. Я понимаю, что в этом ответе не предлагалось использовать google.com:81, но смысл в том, чтобы использовать другой заблокированный порт. Таким образом, вы всегда можете использовать <your-own-ip>: <заблокированный-порт>.
Джеймс Сельвакумар

6
Если это не ваш собственный сервер, то его грубость в том, чтобы поразить другие серверы для вашего тестирования. Используйте цивилизованное решение, такое как упомянутое ниже эму, выбрав немаршрутизируемый IP-адрес, например 10.255.255.1, или настройте собственный виртуальный сервер для тестирования.
Зеешан

2
Я думаю, что Google, возможно, заблокировал этот порт. Когда я тестирую это с Chrome, я просто «Сервер недоступен». Когда я использую трюк @ emu ниже, соединение зависает, как и ожидалось. Я что-то упускаю?
entpnerd

ОП говорит, что он подключился к порту 81 на своем собственном сервере и получил тайм-аут. Это сработало и для меня. Решение эму дало мне исключение UnknownHostException для Android.
Барри Фрутман

2
Это даст соединение отказано не тайм-аут.
Мехди

425

Подключитесь к не маршрутизируемому IP-адресу, например 10.255.255.1.


12
То же самое, и я думаю, что это лучший ответ, так как google.com:81 может быть достигнут однажды.
Gui13

139
... и потому что отправка случайных пакетов на серверы других людей из ваших модульных тестов - это грубо.
Гленн Мейнард

15
Это не всегда работает. Например, для Python urllibэто вернет исключение «No route to host». К вашему сведению
Майк Шульц

8
10.0.0.0, 10.255.255.255, 172.16.0.0, 172.31.255.255, 192.168.0.0, 192.168.255.255 - все они не маршрутизируются.
rajesh_kw

4
Ошибка «No route to host», упомянутая @FHI, обычно появляется в двух случаях: (a) когда вы пытаетесь подключиться к недоступному хосту в вашей локальной сети (это означает, что он не отвечает на запросы ARP, поэтому в основном это «» Тайм-аут ARP "). И (b) когда маршрутизатор возвращает соответствующую ошибку ICMP. Первый случай происходит, если вы находитесь в той же подсети, что и тестируемый вами частный IP-адрес. Второй случай, если маршрутизатор не знает, как направить ваш пакет к месту назначения, но в некоторых случаях он просто отбрасывает пакет без отправки ошибки ICMP.
Але

47

Если вы работаете на Unix-машине, вы можете запустить прослушивание порта, используя netcat:

nc -l 8099

Затем измените ваш сервис так, чтобы он вызывал все, что обычно делает с этим портом, например, http: // localhost: 8099 / some / sort / of / endpoint

Затем ваша служба откроет соединение и запишет данные, но никогда не получит ответ, и, следовательно, предоставит вам тайм-аут чтения (а не отказ в соединении)


1
Это полезно, поскольку вы можете видеть любые данные, которые отправляет ваше приложение. Вы можете проверить, запрашивает ли ваша заявка ответ.
Пол

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

@AlanSE - что ты имеешь в виду? Вы можете иметь что-нибудь после номера порта; Netcat не будет заботиться, так как ему нечего обрабатывать URL-адреса
Том Чемберлен

@ TomChamberlain Ой, подождите, я мог бы знать, что я делал не так. Я пытаюсь смоделировать тайм-аут соединения SSH. Поэтому я даю ему localhost, порт 8099, но ранее я не давал имя пользователя, так что, если я просто что-то вставляю ssh alanse@localhost -p 8099, похоже, что это так.
AlanSE

7
Чтобы проверить время ожидания соединения на уровне сокета, заморозьте процесс nc с помощью kill -STOP <pid>(или просто нажмите CTRL-Z, не вставляя в фоновом режиме). Система будет действовать так, как если бы сервер работал, но подождать, пока сервер примет соединение, что приведет к таймауту соединения (errno 110).
Филант

27

Следующий URL всегда дает время ожидания и объединяет лучшие ответы @Alexander и @ Emu, приведенные выше:

http://example.com:81

Использование example.com:81- это улучшение ответа Александра, потому что example.com зарезервирован стандартом DNS, поэтому он всегда будет недоступен, в отличие от того google.com:81, который может измениться, если Google захочет. Кроме того, поскольку example.comон определен как недоступный, вы не будете наводнять серверы Google.

Я бы сказал, что это улучшение по сравнению с ответом @ emu, потому что его намного легче запомнить.


2
в настоящее время я вижу example.comразрешение до 93.184.216.34 и на самом деле служит короткий HTML-код, объясняющий, что это пример домена ... порт 81 по-прежнему не отвечает.
Бени Чернявский-Паскин

Вопрос в том, действительно ли example.com будет использоваться таким образом. Только если они сделают его официально свободным для заполнения тестовыми пакетами, этот домен будет лучше, чем любой другой коммерческий домен. Использование доменов для таких целей без разрешения, по меньшей мере, если не незаконно, неэтично, потому что обработка этих пакетов обходится кому-то в деньги. Подумайте об использовании в httpstat.usкачестве ответа @AndyTheEntity в своем ответе.
Мануэль

@Manuel Вы упускаете суть ... example.comэто не коммерческий домен, это одно из немногих доменных имен, которые явно указаны как непригодные для использования. Никто не может владеть, example.comи DNS-маршрутизаторы знают, что он никогда не маршрутизирует на реальный адрес. Так что серверное время никому не стоит, в этом нет ничего плохого
speedplane

@speedplane IANA по закону владеет доменом и поддерживает веб-сервер, предоставляющий веб-страницу, объясняющую назначение example.com. За доменом стоит инфраструктура, поэтому каждый запрос стоит денег IANA. На допустимое использование ссылаются в RFC 2606 и RFC 6761. Вы не можете свободно использовать домены для любых целей, например, floddingвместо других серверов, как вы упоминаете. Ваша претензия example.com is defined to be unreachableневерна, она достижима. Порт 81 сейчас недоступен, но где это определено, чтобы быть гарантированным в будущем?
Мануэль

RFC, на который вы указываете, специально разрешает тестирование DNS. Они рекомендуют использовать .testдомен верхнего уровня, а не example.com, но эти домены были явно настроены для этой цели. Да, это может стоить IANA немного денег, но это услуга, которую они предоставляют. Наши DNS-сборы платят за это.
скоростной самолет

23

Множество хороших ответов, но, похоже, самое чистое решение - это услуга

http://httpstat.us/504?sleep=60000

Вы можете настроить время ожидания (до 230 секунд) и возможный код возврата.


16

Вы можете использовать Python REPL для имитации времени ожидания при получении данных (т. Е. После успешного установления соединения). Ничего, кроме стандартной установки Python не требуется.

Python 2.7.4 (default, Apr  6 2013, 19:54:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        
>>> s.bind(('localhost', 9000))
>>> s.listen(0)
>>> (clientsocket, address) = s.accept()

Теперь он ждет входящего соединения. Подключите все, что вы хотите проверить localhost:9000. Когда вы это сделаете, Python примет соединение и accept()вернет его. Если вы не отправляете какие-либо данные через clientsocketсокет, время ожидания следующего звонка должно истечь recv().


Не работает для меня; чего-то не хватает. Возможно s.listen(5)раньше s.accept()?
bmaupin

@bmaupin Это звучит разумно, я просто забыл это. Отредактировал его сейчас (однако с очередью невыполненных заданий 0), спасибо!
Хенрик Хаймбюргер

1
Я смог поместить части «прислушивайся» и «принимай» в while True:цикле, и это, похоже, является хорошим долговременным местом ожидания для тестирования.
AlanSE

2
Он работает, но он дает ошибку «таймаут», который не является таким же , как «Время ожидания соединения»
Timur

13
  • 10.0.0.0
  • 10.255.255.255
  • 172.16.0.0
  • 172.31.255.255
  • 192.168.0.0
  • 192.168.255.255

Все это не маршрутизируемые.


2
(Как я прокомментировал принятый ответ) Когда я тестировал XMLHttpRequest в Node.js, соединения с ошибкой EACCES 10.0.0.0и 10.255.255.255запускались вместо тайм-аута. 10.255.255.1, 172.16.0.0, 172.31.255.255, 192.168.0.0, И 192.168.255.255сделал тайм - аут, однако.
Джейми Бёрч,

9

Я хотел бы обратить внимание всех на патод

С конфигом (взятым из их примеров) 200:b@100:drвы получите соединение, которое случайно сбрасывается.


1
Не то же самое, что тайм-аут
Дентарг

8

Как насчет программного решения:

Установите SSH-сервер на сервер приложений. Затем используйте сокет туннеля для создания связи между вашим локальным портом и удаленным портом на сервере приложений. Вы можете использовать инструменты клиента ssh для этого. Вместо этого подключите ваше клиентское приложение к подключенному локальному порту. Затем вы можете разорвать туннель сокета по желанию, чтобы смоделировать время ожидания соединения.


4

Если вы хотите использовать активное соединение, вы также можете использовать http://httpbin.org/delay/# , где # - время, которое вы хотите, чтобы их сервер ожидал перед отправкой ответа. Пока ваш тайм-аут короче задержки ... должен имитировать эффект. Я успешно использовал его с пакетом запросов Python.

Возможно, вы захотите изменить свой запрос, если отправляете что-то деликатное - понятия не имею, что происходит с отправленными им данными.


Максимум 10 секунд (если вы введете большее число, оно ответит через 10 секунд)
Гарри Вуд

2

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

Например, если вы хотите протестировать запрос, ответ на который занимает 15 секунд, вы просто отправите запрос в API macgyver.

JSON Payload:

{
    "timeout_length": 15000
}

Ответ API (через 15 секунд):

{
    "response": "ok"
}

Программа тайм-аута сервера на macgyver
https://askmacgyver.com/explore/program/server-timeout/3U4s6g6u


1

Вы можете установить драйвер Microsoft Loopback, который создаст для вас отдельный интерфейс. Затем вы можете подключиться к нему к какой-либо вашей службе (ваш собственный хост). Затем в Network Connections вы можете отключить / включить такой интерфейс ...


1

Несмотря на то, что не совсем ясно, какой именно OP хочет проверить: есть разница между попыткой подключения к несуществующему хосту / порту и временем ожидания уже установленного соединения. Я хотел бы пойти с Робом и подождать, пока соединение не заработает, а затем потянуть кабель. Или - для удобства - используйте виртуальную машину, работающую в качестве тестового сервера (с сетевым мостовым соединением), и просто деактивируйте интерфейс виртуальной сети после установления соединения.


1

Техника, которую я часто использую для симуляции времени ожидания случайного соединения, заключается в использовании переадресации локального порта ssh.

ssh -L 12345:realserver.com:80 localhost

Это будет перенаправлять трафик на localhost: 12345 на realserver.com:80. Вы также можете сделать это на своем локальном компьютере, если хотите:

ssh -L 12345:localhost:8080 localhost

Таким образом, вы можете направить ваше приложение на локальный и пользовательский порт, и трафик будет перенаправлен на целевой хост: порт. Затем вы можете выйти из этой оболочки (вам также может понадобиться сочетание клавиш ctrl + c после выхода из нее), и это прекратит переадресацию, в результате чего ваше приложение увидит потерю соединения.


0

Подключите сетевой кабель к коммутатору, который не имеет других подключений / кабелей. Это должно работать имхо.


0

В прошлом я использовал несколько тактик для симуляции сетевых проблем;

  1. Вытащите сетевой кабель
  2. Выключите коммутатор (в идеале, когда коммутатор, к которому подключен компьютер, все еще находится под напряжением, чтобы машина поддерживала свое «сетевое соединение») между вашей машиной и «целевой» машиной
  3. Запустите программное обеспечение брандмауэра на целевой машине, которое автоматически отбрасывает полученные данные.

Одна из этих идей может дать вам некоторые средства для искусственного создания сценария, который вам нужен


0

В зависимости от того, какое программное обеспечение брандмауэра у вас установлено / доступно, вы должны иметь возможность заблокировать исходящий порт, а в зависимости от того, как настроен ваш брандмауэр, он должен просто отбросить пакет запроса на подключение. Нет запроса на соединение, нет соединения, истекло время ожидания. Это, вероятно, сработало бы лучше, если бы оно было реализовано на уровне маршрутизатора (они склонны отбрасывать пакеты, а не отправлять перезагрузки или что-то подобное для ситуации), но обязательно найдется программный пакет, который тоже справится с задачей.


0

Самый простой способ - сбросить соединение с помощью CurrPorts .

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


С помощью CurrPorts мне кажется, что я могу только закрыть соединение (что приводит recv()к немедленному сбою следующего ), но не смог найти способ имитировать тайм-аут (т. Е. Больше не передаются данные, но соединение остается открытым).
Хенрик Хаймбюргер

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

0

У меня были проблемы в том же духе, что и у вас. Чтобы проверить поведение программного обеспечения, я просто отключил сетевой кабель в соответствующее время. Я должен был установить точку останова прямо перед тем, как хотел отключить кабель.

Если бы я делал это снова, я бы вставил переключатель (нормально замкнутая кратковременная кнопка) в сетевой кабель.

Если физическое отключение вызывает другое поведение, вы можете подключить свой компьютер к дешевому концентратору и поместить упомянутый выше коммутатор между вашим концентратором и основной сетью.

- РЕДАКТИРОВАТЬ - Во многих случаях вам потребуется работающее сетевое соединение, пока вы не доберетесь до определенной точки в вашей программе, ТОГДА вы захотите отключиться, используя одно из многих предложенных предложений.


0

Для меня самым простым способом было добавить статический маршрут на офисный маршрутизатор на основе сети назначения. Просто перенаправьте трафик на не отвечающий хост (например, на ваш компьютер), и вы получите тайм-аут запроса.

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


-1

Вы можете попытаться подключиться к одному из известных веб-сайтов через порт, который может быть недоступен извне - например, 200. Большинство брандмауэров работают в режиме DROP, и он будет имитировать время ожидания для вас.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.