人工制造连接超时错误

394

我们的软件出现了一个bug,当我遇到连接超时时,它就会发生。这些错误非常罕见(通常是由于内部网络丢失连接)。我如何人为地产生这种效果以便测试我们的软件?

如果有关系的话,这个应用程序是使用C++/MFC编写的,使用CAsyncSocket类。

编辑:

我已经尝试过使用不存在的主机,但是我得到了套接字错误:

WSAEINVAL (10022) 无效的参数

我的下一步尝试是使用Alexander的建议连接到另一个端口,例如81(但是在我的自己的服务器上)。那很好用。正好和断开连接一样(等待60秒,然后报错)。谢谢!


嗨,马克,我尝试了你提供的解决方案,但我收到的是**#503(服务不可用)。难道不应该是其中之一,#504(网关超时)、#599(网络连接超时错误)、#598**(网络读取超时错误)吗? - CoDe
你想要连接超时还是读取超时? - user207421
22个回答

547

连接到不能路由的 IP 地址,例如 10.255.255.1。


13
同上,我猜这是一个更好的答案,因为 google.com:81 可能有一天会被访问到。 - Gui13
174
发送随机数据包到别人的服务器进行单元测试是不礼貌的。 - Glenn Maynard
15
这种方法并不总是有效的。例如,对于Python的urllib库,这将返回“无法连接到主机”的异常信息。FYI - Mike Shultz
10
这些都是不可路由的IP地址范围。具体为: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
6
@FHI提到的“无法连接到主机”的错误通常出现在两种情况下:(a) 当您尝试连接到本地LAN中不可达的主机时(意思是,它不会回答ARP查询,因此基本上是“ARP超时”)。和(b)当路由器返回相应的ICMP错误时。第一种情况发生在您与要测试的私有IP处于同一子网中的情况下。第二种情况是如果路由器不知道如何将您的数据包路由到其目的地,但在某些情况下,它们会直接丢弃该数据包而不发送ICMP错误。 - Ale
显示剩余5条评论

387

连接到已存在的主机,但是连接的端口被防火墙阻止并且直接丢弃TCP SYN数据包。例如,www.google.com:81。


6
这个答案很简单,与下面 @emu 的回答一样有效。我理解这个答案并没有打算建议使用 google.com:81,而是要用一个被阻塞的不同端口。所以你可以始终使用<你自己的IP>:<被阻止的端口>。 - James Selvakumar
20
除非是你自己的服务器,否则为了测试而攻击其他服务器是不礼貌的。使用类似于 emu 下面提到的文明解决方案,通过攻击非路由 IP 地址(例如 10.255.255.1)或设置自己的虚拟服务器进行测试。 - zeeshan
2
我认为Google可能已经阻止了这个端口。当我使用Chrome测试时,只出现“服务器不可用”错误。当我使用下面@emu的技巧时,连接如预期地挂起。我是不是漏了什么? - entpnerd
3
这将会返回连接被拒绝的错误,而非超时。 - Mehdi
1
我同意@zeeshan的观点,我们生活在一个文明的世界,与其扼杀别人的服务器,不如优化自己的服务器。 - Shobhit Walia
显示剩余4条评论

128

许多好的答案,但最简洁的解决方案似乎是这个服务

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

您可以配置超时持续时间(最长可达230秒)和最终返回代码。


5
这正是我一直在寻找的。服务很棒,我会将其加入我的书签。 - Bond Jerome
1
只是一个小补充,您可能需要使用状态码 200,即 https://httpstat.us/200?sleep=60000,因为当使用 504 时,延迟似乎并没有完全生效 :) - Glenn Mohammad
据我理解,这个请求产生了读取超时而不是连接超时? - Max
1
@Max 我还没有检查,但这是最有道理的,因为必须建立连接才能发出请求(因此服务器会知道延迟多长时间)。 - TheTechRobo the Nerd

65

如果您使用的是Unix系统,您可以使用netcat启动端口侦听:

nc -l 8099

然后,修改您的服务以调用通常对该端口进行的任何操作,例如http://localhost:8099/some/sort/of/endpoint

接下来,您的服务将打开连接并写入数据,但永远不会收到响应,因此将显示读取超时错误(而不是连接被拒绝)


2
这很有用,因为您可以查看应用程序正在推送的任何数据。您可以检查应用程序是否正在请求响应。 - Paul
这适用于导航到某种端点,如上所述,但如果我尝试以其他方式连接,它会迅速拒绝连接,这不是我现在想模拟的行为。 - AlanSE
@AlanSE - 你指的其他方式是什么?端口号后面可以跟任何内容;netcat 不会在意,因为它没有处理任何 URL 的功能。 - Tom Chamberlain
@TomChamberlain 哦,等等,我可能知道我做错了什么。我正在尝试模拟ssh连接超时。所以我给它本地主机,端口8099,但之前我没有给出用户名,所以如果我只是输入ssh alanse@localhost -p 8099,看起来就可以了。 - AlanSE
12
为了在套接字级别测试连接超时,请使用“kill -STOP <pid>”命令冻结nc进程(或者只是在不将其放入后台的情况下按CTRL-Z)。 系统将表现得像服务器正在运行,但等待服务器接受连接,结果会出现连接超时(错误号110)。 - philant
显示剩余7条评论

50

以下URL始终会超时,结合了@Alexander和@Emu的最佳答案:

http://example.com:81

使用example.com:81相对于Alexander的答案来说更好,因为example.com是由DNS标准保留的,所以它永远无法访问,而不像google.com:81,如果Google觉得需要更改,那么它就会更改。另外,因为example.com被定义为无法访问,所以你不会向Google的服务器发送大量请求。

我认为这比@emu的答案更好,因为它更容易记住。


2
目前我看到 example.com 解析为 93.184.216.34,并且实际上提供了一个简短的 HTML,解释它是一个示例域名... 端口81仍然没有响应。 - Beni Cherniavsky-Paskin
1
问题实际上是example.com是否应该以这种方式使用。除非他们正式允许免费发送测试数据包,否则该域名并不比其他商业域名更好。未经许可将域名用于此类目的是不道德的,至少可以说是非法的,因为处理这些数据包需要支付费用。考虑使用@AndyTheEntity在答案中指出的httpstat.us - Manuel
@Manuel 你没有理解重点... example.com 不是商业域名,它是少数明确指定为不可用的域名之一。没有人可以拥有 example.com,DNS 路由器知道它永远不会路由到真实地址。因此,它不会浪费任何服务器时间,使用它没有任何问题。 - speedplane
2
@speedplane IANA根据规定拥有该域名,并维护一个Web服务器,提供解释“example.com”目的的网页。由于该域名背后有基础设施,因此每个请求都会花费IANA的资金。RFC 2606和RFC 6761中引用了可允许使用的内容,您不能自由地将域名用于任何您喜欢的目的,例如像您提到的那样“flodding”它们而不是另一个服务器。您声称“example.com被定义为无法访问”,这是不正确的,它是可以访问的。端口81现在无法访问,但是未来是否保证无法访问呢? - Manuel
你指向的RFC明确允许进行DNS测试。他们建议您使用.test顶级域,而不是example.com,但这些域名显然是为此目的设置的。是的,这可能会花费IANA一些钱,但这是他们提供的服务。我们的DNS费用正在支付它。 - speedplane
与curl 28错误代码完美配合。Google:81给出了curl 7,因此example.com更好。 - A. Denis

21
  • 10.0.0.0
  • 10.255.255.255
  • 172.16.0.0
  • 172.31.255.255
  • 192.168.0.0
  • 192.168.255.255

这些地址都不能被路由器转发。


6
当我测试Node.js中的XMLHttpRequest时,连接到10.0.0.010.255.255.255会触发EACCES错误而不是超时。然而,连接到10.255.255.1172.16.0.0172.31.255.255192.168.0.0192.168.255.255会超时。请注意,这里指的是IP地址连接测试情况。 - Jamie Birch
@JamieBirch,你测试时是不是在10.0.0.0/8的网络内部?或者你的路由器是否意识到这样一个网络,要么是因为它直接连接到该网络,要么是因为它有一个禁止路由到该网络的策略?在所有这些情况下,你都会得到明确的错误而不是超时。 - Mecki
如果您的代码库阻止了它们,因为它们是私有网络、环回地址,那么这些可能不可行。https://en.wikipedia.org/wiki/Private_network https://www.webopedia.com/TERM/A/APIPA.html - user1821961
192.168.0.0 给我返回了 ENETUNREACH,而不是超时。 - UpTheCreek

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.accept()之前加上s.listen(5) - bmaupin
@bmaupin 那听起来很合理,我想我只是忘了。现在已经编辑好了(不过后台队列为0),谢谢! - Henrik Heimbuerger
2
我能够将监听和接受部分放入一个 while True: 循环中,这似乎是一个很好的耐用的超时目标,适合用于测试。 - AlanSE
2
它可以工作,但是会出现“读取超时”错误,这与“连接超时”不同。 - timur
除非你设置了超时时间,否则它不会超时,而你没有设置。 - user207421

11

我想要把大家的注意力引向mitmproxy

使用他们示例中的配置200:b@100:dr,您将获得一个随机断开连接的连接。


2
不同于超时。 - dentarg
2
我想指出@zb226的编辑在这种情况下并不是真正有帮助的。虽然我七年前推荐的pathod现在已成为mitmproxy的一部分,但是这篇文章在当前形式下毫无意义。我找不到关于如何使用mitmproxy实现类似功能的文档,因此我留下了这个评论,供任何想知道如何工作的人参考。 - amenthes
@amenthes 嗯,至少它让你意识到了这个事实 :) - zb226

8

那么,如何使用软件解决方案呢:

在应用服务器上安装SSH服务器。然后,使用socket隧道在本地端口和应用服务器上的远程端口之间创建链接。您可以使用ssh客户端工具来完成这个过程。让客户端应用程序连接到映射的本地端口。然后,您可以随意中断socket隧道以模拟连接超时。


这不会导致连接超时,而是会导致重置。 - user207421

6
如果您想使用一个活动连接,您也可以使用http://httpbin.org/delay/#,其中#是您希望他们的服务器在发送响应之前等待的时间。只要你的超时比延迟短……就应该模拟这种效果。我已经成功地使用了python请求包。如果您正在发送任何敏感信息,您可能需要修改您的请求 - 不知道发送给他们的数据会发生什么。

以下是程序设计相关的内容,已翻译成中文: - Harry Wood
试试https://Beeceptor.com吧!它提供60秒的延迟,帮助模拟超时情况! - ankitjaininfo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接