非常令人困惑的情况:"java.net.ConnectException: Connection refused" 一些主机(一次是这个异常,一次不是!)

Very confusing case: "java.net.ConnectException: Connection refused" by some hosts (one time this exception, one time not!)

我在 Java 中有一个完全正常的 class 用于 HTTP 连接从服务器获取 HTTP 响应 headers。我似乎绝对没问题,它实际上对我测试过的大多数 web-sites 都很好。但是..

    import java.net.HttpURLConnection;
    import java.net.URL;
    public class Main2 {
        public static void main(String[] args) {
            HttpURLConnection.setFollowRedirects(false);
            HttpURLConnection con = null;
            try {
                URL url = new URL("http://sometestsite.blabla/");
                con = (HttpURLConnection) url.openConnection();
                con.setRequestMethod("GET");
                con.connect();

                System.out.println(con.getHeaderField("Server"));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

但是有一些网站,通过用这个 class 测试它们,我得到了一次 "java.net.ConnectException: Connection refused" 异常和第二次......它工作正常(通过相同的主机名)并且我得到一个答案!它如此等等。一次回答一次异常。

异常:

java.net.ConnectException: Connection refused
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at java.net.Socket.connect(Socket.java:538)
    at sun.net.NetworkClient.doConnect(NetworkClient.java:180)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:432)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:527)
    at sun.net.www.http.HttpClient.<init>(HttpClient.java:211)
    at sun.net.www.http.HttpClient.New(HttpClient.java:308)
    at sun.net.www.http.HttpClient.New(HttpClient.java:326)
    at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1169)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1105)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:999)
    at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:933)
    at Main2.main(Main2.java:14)

当我在浏览器中测试相同的主机名时,我总是成为答案。当我在 curl (ubuntu) 中测试相同的主机名时,我总是得到一个答案(所以在这两种情况下都没有例外)。

我真的很困惑,有什么想法请留言。非常感谢!

java.net.ConnectException 在您使用客户端-服务器架构并尝试建立从客户端到服务器的 TCP 连接时发生。现在它发生的原因有很多。我了解您的情况是间歇性,即有时有效,有时无效。

您的客户端代码似乎没有任何问题,无论是服务器还是网络。 Network/Firewall 很少断断续续。我建议您在服务器上进行一系列测试(ping/curl 等),这似乎是这里的问题。

此外,您还可以将这段代码合并到您的客户端中,以更好地调试问题。如果一切都失败了,请与您的网络团队讨论该问题。

public class TestServer {
    public static void main(String[] args){
        try{
            InetAddress address = InetAddress.getByName("192.168.1.1");
            boolean reachable = address.isReachable(10000);
            System.out.println("Host reachable? " + reachable);
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

现在我可以用我上一条评论的信息给出答案了:

Wireshark 给了我一个提示,通过与源端口的连接 > 45000 连接将被接受,通过较小的端口 not.By 第一个连接 Java 选择源端口 36846 和第二个 45852,所以第二个通过 curl 还使用了 2 次尝试:一次使用较小的端口,一次使用较大的端口 (> 51000),这样也通过了。浏览器使用第一次端口 > 45000

结果:似乎是错误配置的火瀑布