如何在本地端口上模拟网络延迟?
Posted
技术标签:
【中文标题】如何在本地端口上模拟网络延迟?【英文标题】:How to simulate network delay on a local port? 【发布时间】:2017-12-09 08:15:11 【问题描述】:我想看看 HTTP 客户端如何对连接超时做出反应,即有服务器在端口上侦听,但建立连接的过程太慢以至于客户端放弃并返回连接超时。连接不应该被拒绝,也不应该被接受,然后是套接字超时。
到目前为止,我已经尝试通过覆盖ServerSocket
来引入网络延迟,想象我可以写出这样的东西......
public SlowServerSocket extends ServerSocket
// (This method doesn't actually exist).
@Override
public void processBytesPassedOnByOperatingSystem(byte[] bytes)
Thread.sleep(delay);
// Client has already returned a connection timeout.
super.processBytesPassedOnByOperatingSystem(bytes);
...但是当我达到那个抽象级别时我遇到了死胡同(它似乎隐藏在本机方法中)。我的假服务器接受连接,然后什么也不做,导致套接字超时。
我也在网上寻找解决方案,我从 JMeter 库中找到了SlowSocket
,但它似乎用于客户端(而且我认为我无法覆盖客户端,以便它使用SlowSocket
)。
有什么建议吗?
【问题讨论】:
注意:我找到了这个答案,***.com/questions/100841/…,它建议连接到不可路由的地址,例如“10.255.255.1”。但是,我不确定它是否是最可靠/便携的解决方案。 可能还值得继承SecurityManager
并覆盖 checkAccept()
方法以使其休眠,然后调用 System.setSecurityManager(overridenSecurityManager)。想法来自这里:***.com/questions/7800960/…
【参考方案1】:
我想看看 HTTP 客户端如何对连接超时做出反应,即有一个服务器正在侦听一个端口,但是建立连接的过程太慢以至于客户端放弃并返回一个连接超时。
您的要求在术语上体现了矛盾。当对等 host 根本没有响应时,会发生连接超时,通常是因为防火墙。它与服务器应用程序缓慢无关。服务器不会“建立连接”:TCP 堆栈会。
不应拒绝连接
如果有监听过程就不会了,除了下面的情况。
它不应该被接受,然后是套接字超时。
这正是您编写的代码将产生的结果。
然而,并且当且仅当服务器平台不是Windows,还有另一种产生连接超时的方法:让积压队列填满。为此,请让服务器执行所有正常的套接字设置步骤,但根本不调用accept()
,并让客户端执行大量连接尝试。但是如果服务器平台是Windows,就会产生连接拒绝。
【讨论】:
所以当“TCP堆栈”(对不起,我对这方面的知识很少)无法连接到目标端口时,连接被拒绝,因为该端口上没有进程监听?当 TCP 数据包甚至没有到达目的地/响应没有及时返回时,连接就会超时? @Pig 如果没有监听进程,或者积压队列已满且服务器平台为Windows,则连接被拒绝。我已经说过了。如果对等方没有及时响应或根本没有响应,则连接超时。我也说过了。【参考方案2】:我也在网上寻找解决方案,我从 JMeter 库中遇到了 SlowSocket,但它似乎是在客户端使用的(而且我认为我无法覆盖客户端所以它使用的是 SlowSocket)。
您可以使用Sniffy 来模拟网络延迟 - 它与 Java TCP 堆栈无缝集成,并且不需要从应用程序端进行任何更改。见documentation on emulating network issues。
demo.sniffy.io 提供在线演示 - 单击右下角的小部件,转到 “网络连接” 选项卡并设置 延迟 为 1000 毫秒 en.wikipedia.org。刷新浏览器页面,您会看到加载页面需要多花 1 秒时间。 javaagent integration 也可用于非 Web 应用程序。
免责声明:我是Sniffy的作者
【讨论】:
但它会模拟慢速连接阶段吗?如果是,怎么做? TCP 中的连接阶段基本上为第一个数据包增加了额外的往返行程(SYN 和 SYN-ACK 数据包不带应用程序数据;它仅与 ACK 数据包一起发送)。在 Java 应用程序中,无法访问 IP 数据包,因此 Sniffy 使用一些启发式方法来添加延迟,如下所述:sniffy.io/docs/latest/#_emulating_network_issues;在客户端的 Socket.connect() 方法中添加了指定的延迟 这不是我们要求的。他想看看他的现有客户端如何对连接超时做出反应,而你所做的任何事情都不会导致。 @EJP Sniffy 允许测试 现有 客户端如何对网络延迟做出反应,而无需修改它们。您只需将 -javaagent:sniffy... 添加到命令行参数。在给定延迟后模拟超时异常也是可能的。 所以,再次告诉我们它是如何产生连接超时的。当我之前两次问这个问题时,你在上面给出的答案是不充分的。延迟 client 不会导致连接超时。只有服务器或网络可以做到这一点。以上是关于如何在本地端口上模拟网络延迟?的主要内容,如果未能解决你的问题,请参考以下文章