【问题标题】:Making a connection with Socket.connect using timeout使用超时与 Socket.connect 建立连接
【发布时间】:2013-01-24 12:05:02
【问题描述】:

我正在使用 Socket 类建立一个 java TCP 连接。

Socket socket = new Socket();
socket.connect(new InetSocketAddress(host,port),50);

我希望快速建立或根本不建立此连接,因此我使用 50 毫秒作为连接超时时间。

但如果我测量这些调用之间的时间,我会得到超过 50 毫秒:125 毫秒,甚至 200 毫秒。测量我使用 System.currentMillis() 的时间。我知道这种方法的粒度不是很好,但是+100ms的差异实在是太荒谬了。

connect方法有问题?超时时间太短了 50 毫秒?我在 Windows 7 中使用 java 1.7.0_03。

【问题讨论】:

  • 如果没有详细的实施知识,我不确定这是否可以回答。底层操作系统也有可能对超时值使用某个最小值或粒度。还要考虑从主机名解析 IP 地址所需的时间;这不是连接超时 AFAIK 的一部分。
  • 您衡量的是连接成功还是失败?
  • 也有可能只有第一次连接尝试需要很长时间。尝试在 100 个连接的循环中对其进行测量。
  • 50ms 对于网络超时来说太短了。使用几秒钟之类的实际值。
  • 我正在测量成功和失败的连接,在一个有超过 100 个连接的循环中,所花费的时间只是不一致(62,55,67,251,104...)。我使用的主机格式为“xxx.xxx.xxx.xxx”,所以我认为不涉及任何 ip 解析。奇怪的是,当我使用私有网络“192.168.1.x”中的主机时,不会出现不一致的超时。

标签: java sockets connection timeout


【解决方案1】:

在 tdn120 的 answer 上扩展我将 println 移动到最后。我始终

javac -g SocketTest.java && java SocketTest localhost:80 abcd.com:80 localhost:80 localhost:80 localhost:80 
Testing: localhost:80
java.net.SocketTimeoutException: connect timed out
Time: 63
Testing: abcd.com:80
java.net.UnknownHostException: abcd.com
Time: 2350
Testing: localhost:80
java.net.SocketTimeoutException: connect timed out
Time: 50
Testing: localhost:80
java.net.SocketTimeoutException: connect timed out
Time: 50
Testing: localhost:80
java.net.SocketTimeoutException: connect timed out
Time: 50

我的代码如下:

import java.net.*;

public class SocketTest {
    public static void main(String[] args) throws Exception {
        if (args.length == 0) {
            args = new String[]{"localhost:80"};
        }
        for (String target: args) {
            test(target);
        }
    }

    private static void test(String target) throws Exception {
        System.out.println("Testing: " + target);
        String[] parts = target.split(":");
        String host = parts[0];
        int port = Integer.valueOf(parts[1]);
        Socket socket = new Socket();
        long start = 0;
        try {
            start = System.nanoTime();
            socket.connect(new InetSocketAddress(host, port), 50);
        } catch (Exception e) {
            System.out.println(e.toString());
        } finally {
            long end = System.nanoTime();
            System.out.println("Time: " + ((end - start) / 1000000));
        }
    }
}

【讨论】:

  • 是的,但那是我不明白的。在您的示例中,您得到 63 和 2350。这是为什么呢?我的意思是您告诉该方法您不想等待超过 50 毫秒,那么为什么需要更长的时间。高达2350!也许您传递给 connect 方法的超时只是一种建议......
  • 我希望你会注意到额外的时间。 50 毫秒是套接字连接超时。当我使用名称而不是 i/p,尤其是无效名称 (abcd.com) 时,dns 失败需要更多时间。
  • 在执行 socket.close() 操作之后,我在 finally 子句中测量总时间。看来这需要很多时间:(
【解决方案2】:

我感觉这与你的计时方式有关。您需要确保在执行之前和之后立即记录时间。

虽然我使用的是 Linux,但我始终使用以下代码得到 51 或 52 的结果:

public class SocketTest {
    public static void main(final String[] args) throws IOException {
        Socket socket = new Socket();
        long start = 0;
        try {
            start = System.nanoTime();
            socket.connect(new InetSocketAddress("192.168.1.100", 80), 50);
        } catch (SocketTimeoutException e) {
            long end = System.nanoTime();
            System.out.println("Time: " + ((end - start) / 1000000));
        }
    }
}

更新:我在 Windows 7 中尝试过,我得到了 50 和 51。

【讨论】:

  • 我测量的时间和你一样(但使用 currentMillis 而不是 nanoTime)。实际上,当我使用私有网络中的主机时,我得到 50 和 51,但当我使用外部 ips 时却没有。
猜你喜欢
  • 1970-01-01
  • 2021-02-28
  • 2018-12-29
  • 1970-01-01
  • 2021-04-18
  • 1970-01-01
  • 2017-04-10
  • 2017-10-15
  • 1970-01-01
相关资源
最近更新 更多