为什么会出现此错误:打印异常连接在运行时被拒绝

Why this error Exception print Connection refused on running

提问人:Saeed Kiarsi Zadeh 提问时间:11/15/2023 更新时间:11/16/2023 访问量:75

问:

看看这个循环。我想做一个小型端口扫描仪的例子。

for (int port = 1; port <= 65300; port++) {
    try (Socket socket = new Socket("localhost", port)){
        socket.close();
        System.out.println("Port " + port + " Listen.");
    } catch (UnknownHostException uhe){
        System.out.println(uhe.toString());
        break;
    } catch (Exception e) {
        System.out.println("Something went wrong.");
    }
}

当我编写代码打印时:System.out.println(e.toString());

java.net.ConnectException: Connection refused (Connection refused)

但是当我删除它时,代码运行良好。如果你知道,告诉我为什么会这样。

谢谢

Java 异常 错误处理

评论

1赞 seenukarthi 11/15/2023
System.out.println(e.toString());当您删除未打印的邮件时,打印异常消息,但异常仍然发生,只是您没有打印它。如果你对为什么没有打印“Something went wrong.”感到困惑,你需要了解异常捕获是如何工作的,检查 stackoverflow.com/questions/34191745/...
0赞 Saeed Kiarsi Zadeh 11/15/2023
那么我的代码有什么问题呢?当我删除该异常时,我收到错误Socket socket = new Socket("localhost", port)
0赞 seenukarthi 11/15/2023
你的意思是当你移除 catch 块时?
1赞 seenukarthi 11/15/2023
这是因为抛出两个已检查的异常,您必须在代码中显式处理这些异常。你这样做是为了而不是因为是当你添加带有句柄的 catch 块时的超类new Socket("localhost", port)UnknownHostExceptionIOExceptionUnknownHostExceptionIOExceptionExceptionIOExceptionExceptionIOException
2赞 Slaw 11/15/2023
您应该看到“连接被拒绝”异常,因为计算机上的每个端口都不太可能有服务器侦听和接受连接。有关更多信息,请参阅 java.net.ConnectException: Connection rejected Q&A。

答:

1赞 DevilsHnd - 退した 11/15/2023 #1

我不想告诉你这个,但是,你试图这样做的方式将需要很长时间才能通过 65535 个端口。尝试在任何端口的套接字连接上设置超时,以至少在一定程度上加快该过程......大概是 50 毫秒。我想这取决于你拥有的系统。您可以使用 Socket#connect() 方法执行此操作。现在,像 、(或 )这样的 IOException 基本上意味着端口已关闭或根本不可用(对您来说,这也可以被视为已关闭)。生成系统硬件或软件的异常消息或将由系统硬件或软件使用的端口,并且仅针对其特定用途进行保护。connect timed outPermission denied:Connection refusedPermission denied:Connection refused

在我看来,最好的办法是运行扫描考虑几个 ExecutorService 线程(也许像 3000 个),以便在 30 到 40 秒左右完成工作。是的。。。您的盒子会多抽一点血,但是,它胜过等待一整天才能完成端口扫描。

我建议您在扫描过程中不要显示关闭或不可用的端口......这是浪费时间。将输出发送到控制台窗口需要大量不必要的处理时间。只需将开放端口存储在某种集合中,然后在端口扫描完成后将该开放端口集合显示到控制台(或其他任何位置)。下面的可运行演示代码利用了 LinkedHashMap,以便插入到映射中的开放端口号保持插入顺序。

除非您修改代码以运行多个线程,否则我建议您将 int 变量设置为 1000(或 2000),以便更好地了解扫描 65000 个端口需要多长时间。它应该足以给你一些结果(我希望)。portEnd

这是可运行的演示代码。请务必阅读其中的评论:

final int timeout = 50;         // Socket Connection timeout in milliseconds
final int portStart = 1;        // 1 to 65535
final int portEnd = 65535;      // 1 to 65535 
final String ip = "127.0.0.1";  // Local IP.
java.util.LinkedHashMap<Integer, String> openPorts = new java.util.LinkedHashMap<>();
    
System.out.println("Scanning Ports: " + portStart + " To " + portEnd + ". Please Wait!");
System.out.print("Finished Scanning Ports Up To: -> ");
for (int port = portStart; port <= portEnd; port++) {
    /* This increases the Scan time but at least 
       it tells you that something is happenning:  */
    if (port % 100 == 0) {
        System.out.print(port + " ");
    }
    try (java.net.Socket socket = new java.net.Socket()) {
        // Open a connection to the current port Number:
        socket.connect(new java.net.InetSocketAddress(ip, port), timeout);
        // If successful, then the port is Open. If not, an Exception occurs.
        openPorts.put(port, "is Open!");
    }
    catch (java.io.IOException ex) {
        /* This takes time to process as well. It's only here 
           if for some reason something critical happens:  */
        String errMsg = ex.getMessage().toLowerCase(); 
        if (!errMsg.contains("connect timed out") && 
                    !errMsg.contains("permission denied:") && 
                    !errMsg.contains("connection refused")) {
            System.out.println("Port: " + port + " -> *** " 
                                 + ex.getMessage() + " ***"); 
        }
    }
}
    
// Display open ports in Console Window:
System.out.println(System.lineSeparator());
System.out.println("Port Scan Results - Open Ports:");
System.out.println("===============================");
    
// Read the LinkedHashMap:
for (java.util.Map.Entry<Integer, String> mapElement : openPorts.entrySet()) { 
    Integer keyPort = mapElement.getKey(); 

    // Finding the value using getValue() method: 
    String openClosed = mapElement.getValue(); 

    // Print the key-value pairs the way we want:
    System.out.println(String.format("Port #%-6d %-8s", keyPort, openClosed)); 
} 

评论

0赞 Saeed Kiarsi Zadeh 11/15/2023
我复制并粘贴了您的代码,但再次出现错误,那么此错误可能是由于系统中的某些问题而发生的吗?还有其他事情,它只是在我使用循环时发生,但在扫描一个端口时,这不是问题。Connection refused (Connection refused)
0赞 Slaw 11/16/2023
@SaeedKiarsiZadeh 哪个端口抛出“连接被拒绝”异常?为什么您希望连接到该特定端口应该成功?
0赞 DevilsHnd - 退した 11/16/2023
系统硬件(或软件)很可能已保护该端口(以及很可能的其他端口)以供其特定使用。它与 相同。将其视为您的封闭端口,并将消息添加到块中,例如:.Permission DeniedIOExceptionString errMsg = ex.getMessage().toLowerCase(); if (!errMsg.contains("connect timed out") && !errMsg.contains("permission denied:") && !errMsg.contains("connection refused")) { System.out.println("Port: " + port + " -> *** " + ex.getMessage() + " ***"); }