测试 HTTP 延迟的短代码?

Short code to test HTTP latency?

有一些不错的库,例如 this from Apache,但对于我的目的而言,这有点太复杂了。我所需要的只是获得 HTTP 延迟的最佳估计值(与服务器连接 所需的时间,无论传输速度如何)。

我尝试了来自 this answer 的 HTTP 连接代码:

  private void doPing() {
    //Remember time before connection
    long millis = System.currentTimeMillis();
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"))) {
      //We don't need any data
      reader.close();
      //Times is the array where we store our results
      times.add((int)(System.currentTimeMillis()-millis));
      //I see lot's of these in console, so it's probably working
      System.out.println("Request done...");
    }
    //If internet is dead, does it throw exception?
    catch(Exception e) {
      times.add(-1);
    }
  }

问题是我不太确定我在测量什么。遍历值给了我这个结果:

Testing connection to http://www.seznam.cz
      Threads: 5
      Loops per thread: 50
Given up waiting for results.
Average time to connection: 53.8 [ms]
Failures: 0.0%

Testing connection to http://www.seznam.cz
      Threads: 5
      Loops per thread: 100
Average time to connection: 43.58 [ms]
Failures: 0.0%

Testing connection to http://www.seznam.cz
      Threads: 5
      Loops per thread: 400
Average time to connection: 30.145 [ms]
Failures: 0.0%

Testing connection to http://www.whosebug.com
      Threads: 5
      Loops per thread: 30
Given up waiting for results.
Average time to connection: 4006.1111111111113 [ms]
Failures: 0.0%

Testing connection to http://www.whosebug.com
      Threads: 5
      Loops per thread: 80
Given up waiting for results.
Average time to connection: 2098.695652173913 [ms]
Failures: 0.0%

Testing connection to http://www.whosebug.com
      Threads: 5
      Loops per thread: 200
Given up waiting for results.
Average time to connection: 0.0 [ms]
//Whoops, connection dropped again
Failures: 100.0%

//Some random invalid url
Testing connection to http://www.sdsfdser.tk/
      Threads: 4
      Loops per thread: 20
Average time to connection: 0.0 [ms]
Failures: 100.0%

不仅我不确定我是否计算出了我想要的东西(虽然它反映了我的经验),我也不确定在非标准情况下会发生什么。

虽然记住这个项目应该是简单和轻量级的,但你能告诉我我做的是否正确吗?

我认为海林建议您创建一个原始 Socket 并将其连接到服务器,而不是使用 URLConnection。我都试过了,你的版本延迟更高。我认为打开 URLConnection 一定是在后台做一些额外的事情,虽然我不确定是什么。

无论如何,这里是使用 Socket 的版本(根据需要添加异常处理):

Socket s = new Socket();
SocketAddress a = new InetSocketAddress("www.google.com", 80);
int timeoutMillis = 2000;
long start = System.currentTimeMillis();
try {
    s.connect(a, timeoutMillis);
} catch (SocketTimeoutException e) {
    // timeout
} catch (IOException e) {
    // some other exception
}
long stop = System.currentTimeMillis();
times.add(stop - start);
try {
    s.close();
} catch (IOException e) {
    // closing failed
}

这会解析主机名(示例中的 www.google.com),在端口 80 上建立 TCP 连接并将其花费的毫秒数添加到 times如果你不想要那里的 DNS 解析时间,你可以在启动计时器之前创建一个 InetAddress with InetAddress.getByName("hostname") 并将其传递给 InetSocketAddress 构造函数。

编辑:InetSocketAddress 的构造函数也会立即解析主机名,因此从已解析的 ip 地址构造它不会有什么不同。