Java development technology: Socket programming port scanning applet (complete source code)

table of Contents

1. Port scanning technology

Two, single thread to establish Socket connection

Three, based on TCP Connect port scanning

Four, multi-threaded TCP connection scanning

Five, the complete source code of the small program


1. Port scanning technology

We all know that every machine in the network has an IP address. The port of the host is closely related to the IP address. By the way, do you know the range of port numbers?

That's right, it is 0~65535 . In computer networks, two bytes are used for 16-bit binary numbers to represent the port number . For these port numbers, which port numbers does a host open?

For example , the two common port numbers 80 and 443 correspond to HTTP and HTTPS services , port 23 corresponds to telnet remote management , and port 25 is SMTP service. and so on. Let's implement a simple port scanning applet.

Scanning the open ports of the host is a common operation: attack (find the open ports of the destination host) and defense (detect the abnormally open ports of the machine). Techniques that can be used for basic port scanning:

  • Create Socket connection: new Socket(ip,port)
  • TCP Connect detection

This article is suitable for partners of computer network, Java development, Socket programming, and multi-threaded entry! It can be combined with the previous article "Java Development Host IP Scanning Artifact" to further detect useful information on network attack and defense!

Two, single thread to establish Socket connection

Now start the simple development process of small programs, starting from a single thread and moving forward step by step.

Socket socket=new Socket(host,port);

Here, we create a Socket connection. The principle of this method is to establish a connection with the target IP and monitor the port. If it exceeds a certain period of time, it means that the port is not open and the connection cannot be successful.

IOException will be thrown if the connection is not possible   . Therefore, it can be determined that the port is closed when the exception is thrown.

The specific implementation is very simple. We put the operation of scanning ports in a thread without affecting the operation of the main program, and then connect the given port range, such as 0 to 100, one by one Socket connection, so that we can know which ports are open of.

 try {     Socket socket=new Socket(host,port);     socket.close();     Platform.runLater(() -> {          result.appendText("端口 " +port+ " is open.\n");     });} catch (IOException e) {   result.appendText("端口 " +port+ " is closed.\n");}

This is the result of a partial port scan of my host.

The following is a moving picture to see the process.

Three, based on TCP Connect port scanning

From the scanning process of the dynamic image, we can find that this speed is obviously not tolerable, just like a webpage has not been displayed for a long time after loading. Therefore, in order to better user experience, optimize and improve on this basis, the most important It is the scanning speed!

In the previous method, the waiting time is too long when the port is closed, and the time cost is too high. Start using another method, port scanning based on TCP Connect.

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

At this time, no real connection is established for each ip and port, but the "probing" method is used to connect through the InetSocketAddress class, and the timeout period is set to 200ms . Obviously, the speed can be increased by at least several times!

The code implementation is very simple, so write it

try {    Socket socket=new Socket();    socket.connect(new InetSocketAddress(host,port),200);     socket.close();    Platform.runLater(() -> {        result.appendText("端口 " +port+ " is open.\n");    });} catch (IOException e) {    result.appendText("端口 " +port+ " is closed.\n");}

The comparison scan speed after optimization and improvement is as follows:

In contrast, the scanning speed is greatly improved!

At this time, the speed increase is relatively speaking. For example, if you scan 1000 ports, you know how slow it is, and you can’t wait!

Less than 80 ports can be scanned in 20 seconds! Rough calculations, it takes at least 4 minutes for 1000 ports, which is unacceptable!

Four, multi-threaded TCP connection scanning

At this time, you can only use the back hand, multi-threaded special session... Hey

Our small goal now is to be fast, multi-threaded operation is really not bad. Here I start 100 threads to complete this scanning task.

for (int i=0;i<100;i++) {    readThread=new Thread(new ScanHandler(i, 100),"scanThread");    readThread.start();}

At the same time, you need to pay attention to thread safety issues when you start multi-threading. In this task, you also need to pay attention to the port range that each thread is responsible for to avoid repeated scanning and judgment of the end of the scan.

Use atomic variables to ensure thread safety and count correctly to solve the above problems.

static AtomicInteger portCount portCount=new AtomicInteger(0);

Define a scanning thread processing class ScanHandler, the processing logic is roughly: each thread has its own identification number, according to the identification number to determine its own port number, each thread maintains the atomic count of scanned ports .

    class ScanHandler implements Runnable{        private int totalThreadNum;//用于端口扫描的总共线程数量,默认为10        private int threadNo;//线程号,表示第几个线程        private int startP=Integer.parseInt(startPort.getText());        private int endP=Integer.parseInt(endPort.getText());        private String host = targetIP.getText().trim();         public ScanHandler(int threadNo) {            this.totalThreadNum = 10;            this.threadNo = threadNo;        }         public ScanHandler(int threadNo,int totalThreadNum) {            this.totalThreadNum = totalThreadNum;            this.threadNo = threadNo;        }         @Override        public void run() {            //startPort和endPort为成员变量,表示需要扫描的起止端口            for (int i=startP+threadNo;i<=endP;i=i+totalThreadNum){                int port=i;                if (readThread.isInterrupted()){                    readThread.interrupt();                    break;                }                try {                    Socket socket=new Socket();                    socket.connect(new InetSocketAddress(host,port),200);                    socket.close();                    Platform.runLater(() -> {                        result.appendText("端口 " +port+ " is open.\n");                    });                }catch (IOException e){//                    result.appendText("端口 " +i+ " is closed.\n");                }                portCount.incrementAndGet();             }            if (portCount.get()==(endP-startP+1)){//判断扫描结束                portCount.incrementAndGet();                Platform.runLater(()->{                    result.appendText("\n-------------多线程扫描结束-------------\n");                });            }        }    }

Let's take a look at how fast the multi-threaded operation is. Now it feels very smooth. 1000 ports can be scanned in less than 10 seconds!

Doesn’t it feel perfect, but according to common sense, it’s almost always something. It’s actually a progress bar display. Just like when we download something, there is a progress bar and percentage.

There is a progress class that can be used directly in Java, which is the following line of code, which is then added to the scanning thread to update the progress in real time.

ProgressBar progressBar=new ProgressBar();

Let's take a look at the effect, scan 5000 ports with the multi-threaded version.

Five, the complete source code of the small program

Complete source code, without reservation, it is recommended to collect it decisively, so as not to find it for future use!

/** * HostScannerFX.java * Copyright (c) 2021 Charzous * All right reserved. * @date 2021-06-07 下午 09:38 */  import javafx.application.Application;import javafx.application.Platform;import javafx.geometry.Insets;import javafx.geometry.Pos;import javafx.scene.Scene;import javafx.scene.control.*;import javafx.scene.layout.BorderPane;import javafx.scene.layout.HBox;import javafx.scene.layout.Priority;import javafx.scene.layout.VBox;import javafx.stage.Stage;  import java.io.IOException;import java.net.InetSocketAddress;import java.net.Socket;import java.util.concurrent.atomic.AtomicInteger; public class PortScannerFX extends Application {    private TextArea result = new TextArea();    private TextField targetIP = new TextField();    private TextField startPort = new TextField();    private TextField endPort = new TextField();    private Button scan = new Button("扫描");    private Button quickScan = new Button("快速扫描");    private Button threadScan = new Button("多线程扫描");    private Button ex=new Button("退出");    private Button stop=new Button("停止扫描");    private Thread readThread;    static AtomicInteger portCount;//用于统计已扫描的端口数量     private ProgressBar progressBar=new ProgressBar();    private Label bar=new Label("0%");     @Override    public void start(Stage primaryStage) throws Exception {        BorderPane mainPane = new BorderPane();         HBox barBox=new HBox();        barBox.setSpacing(10);        barBox.setPadding(new Insets(10, 0, 10, 0));        progressBar.setPrefWidth(700);        progressBar.setProgress(0);        HBox.setHgrow(progressBar,Priority.ALWAYS);        barBox.getChildren().addAll(bar,progressBar);         VBox vBox = new VBox();        vBox.setSpacing(10);        vBox.setPadding(new Insets(10, 20, 10, 20));//        vBox.setAlignment(Pos.CENTER);        VBox.setVgrow(result, Priority.ALWAYS);        vBox.getChildren().addAll(new Label("端口扫描结果:"), result,barBox);        mainPane.setCenter(vBox);         startPort.setPrefWidth(60);        endPort.setPrefWidth(60);        HBox hBox1 = new HBox();        hBox1.setSpacing(10);        hBox1.setPadding(new Insets(10, 20, 10, 20));        hBox1.setAlignment(Pos.CENTER);        hBox1.getChildren().addAll(new Label("目标主机ip:"), targetIP, new Label("起始端口号:"), startPort, new Label("结束端口号:"),endPort);         HBox hBox2 = new HBox();        hBox2.setSpacing(10);        hBox2.setPadding(new Insets(10, 20, 10, 20));        hBox2.setAlignment(Pos.CENTER);         hBox2.getChildren().addAll(scan,quickScan,threadScan,stop,ex);         VBox vBox1 = new VBox();        vBox1.setSpacing(10);        vBox1.setPadding(new Insets(10, 20, 10, 20));        vBox1.setAlignment(Pos.CENTER);        vBox1.getChildren().addAll(hBox1, hBox2);        mainPane.setBottom(vBox1);         Scene scene = new Scene(mainPane, 800, 500);        primaryStage.setScene(scene);        primaryStage.setTitle("PortScannerFX");        primaryStage.show();           //扫描        scan.setOnAction(event -> {            String host = targetIP.getText().trim();            int sp = Integer.parseInt(startPort.getText());            int ep=Integer.parseInt(endPort.getText());            readThread = new Thread(() -> {                 double num=0.0;                for (int i = sp; i <= ep; i++) {                    int port=i;                    if (readThread.isInterrupted()){                        readThread.interrupt();//                        Thread.interrupted();                        break;                    }                    try {                        Socket socket=new Socket(host,port);                        socket.close();                        Platform.runLater(() -> {                                result.appendText("端口 " +port+ " is open.\n");                        });                    } catch (IOException e) {                        result.appendText("端口 " +port+ " is closed.\n");                    }                    num++;                    double finalNum = num;                    Platform.runLater(()->{                        progressBar.setProgress(finalNum/(ep-sp+1));//进度条                        bar.setText(""+ Integer.valueOf((int) (finalNum /(ep-sp+1)*100))+"%");                    });                }                result.appendText("端口扫描结束!\n");            },"scanThread");            readThread.start();         });         //快速扫描        quickScan.setOnAction(event -> {            String host = targetIP.getText().trim();            int sp = Integer.parseInt(startPort.getText());            int ep=Integer.parseInt(endPort.getText());            readThread = new Thread(() -> {                 double num=0;                for (int i = sp; i <= ep; i++) {                    if (readThread.isInterrupted()){                        readThread.interrupt();//                        Thread.interrupted();                        break;                    }                    int port=i;                    try {                        Socket socket=new Socket();                        socket.connect(new InetSocketAddress(host,port),200);                         socket.close();                        Platform.runLater(() -> {                            result.appendText("端口 " +port+ " is open.\n");                        });                    } catch (IOException e) {                        result.appendText("端口 " +port+ " is closed.\n");                    }                    num++;                    double finalNum = num;                    Platform.runLater(()->{                        progressBar.setProgress(finalNum/(ep-sp+1));//进度条                        bar.setText(""+ Integer.valueOf((int) (finalNum /(ep-sp+1)*100))+"%");                    });                }                result.appendText("端口扫描结束!\n");            },"scanThread");            readThread.start();        });         threadScan.setOnAction(event -> {            portCount=new AtomicInteger(0);            int sp = Integer.parseInt(startPort.getText());            int ep=Integer.parseInt(endPort.getText());            for (int i=0;i<100;i++) {                readThread=new Thread(new ScanHandler(i, 100),"scanThread");                readThread.start();            }        });         stop.setOnAction(event -> {            interrupt("scanThread");        });         //退出        ex.setOnAction(event -> {            exit();        });        primaryStage.setOnCloseRequest(event -> {            exit();        });    }     public void interrupt(String threadName){        ThreadGroup currentGroup=Thread.currentThread().getThreadGroup();        int noThreads=currentGroup.activeCount();        Thread[] lstThreads=new Thread[noThreads];        currentGroup.enumerate(lstThreads);        for (int i=0;i<noThreads;i++){            if (lstThreads[i].getName().equals(threadName))                lstThreads[i].interrupt();        }    }     public void exit(){        System.exit(0);    }       class ScanHandler implements Runnable{        private int totalThreadNum;//用于端口扫描的总共线程数量,默认为10        private int threadNo;//线程号,表示第几个线程        private int startP=Integer.parseInt(startPort.getText());        private int endP=Integer.parseInt(endPort.getText());        private String host = targetIP.getText().trim();         public ScanHandler(int threadNo) {            this.totalThreadNum = 10;            this.threadNo = threadNo;        }         public ScanHandler(int threadNo,int totalThreadNum) {            this.totalThreadNum = totalThreadNum;            this.threadNo = threadNo;        }         @Override        public void run() {            //startPort和endPort为成员变量,表示需要扫描的起止端口            for (int i=startP+threadNo;i<=endP;i=i+totalThreadNum){                int port=i;                if (readThread.isInterrupted()){                    readThread.interrupt();                    break;                }                try {                    Socket socket=new Socket();                    socket.connect(new InetSocketAddress(host,port),200);                    socket.close();                    Platform.runLater(() -> {                        result.appendText("端口 " +port+ " is open.\n");                    });                }catch (IOException e){//                    result.appendText("端口 " +i+ " is closed.\n");                }                portCount.incrementAndGet();                Platform.runLater(()->{                    bar.setText(""+ Integer.valueOf((int) ((portCount.doubleValue())/(endP-startP+1)*100))+"%");//进度比                    progressBar.setProgress((portCount.doubleValue())/(endP-startP+1));//进度条                });            }            if (portCount.get()==(endP-startP+1)){//判断扫描结束                portCount.incrementAndGet();                Platform.runLater(()->{                    result.appendText("\n-------------多线程扫描结束-------------\n");                });            }        }    }      public static void main(String[] args) {        launch();    }}  

Complete source code without reservation, it is recommended to collect it decisively, so as not to find it in future use, and quickly develop a simple port scanning applet by yourself!

Today we use Java development technology: Socket programming port scanning applet , zero-based Socket programming detailed tutorial, is this content simple, interesting and rewarding? Welcome to exchange and learn!

The last thing I want to tell you is, what are the necessary knowledge to learn Java? Many fans have privately sent messages to my Java learning route. I recommend this knowledge graph. The fans think the quality is very good!

Learn Java development, Socket network programming and other knowledge, there are many interesting small programs to do. Recently, I am also following this set of "Java Engineer Learning and Growth Knowledge Graph" to study the system , which is officially launched by CSDN, and the quality is very good. !

It contains the complete and detailed Java professional architecture. It is recommended for everyone to learn and use. If you are interested, you can scan the code to view it . Recently I am also studying. Of course, my article will record the study. Welcome everyone to read, such as my column "Socket Network Programming", "Java Treasure" .

The expansion is like this, the size of 870mm*560mm is beautiful and the content is very substantial . Recommend to partners in need to learn Java development together!


If you think it's good, welcome to "one-click three-link", like, favorite, follow, comment, ask questions and suggestions, welcome to exchange and learn! Let's work hard and make progress together, see you in the next article!

The content of this article is first published on my CSDN blog: https://csdn-czh.blog.csdn.net/article/details/117672622