基于Java編寫一個簡單的內部網(wǎng)段掃描程序
說明
這段代碼實現(xiàn)了一個簡單的內部網(wǎng)段掃描工具,基于 Java Swing 構建圖形用戶界面(GUI),并使用多線程來掃描本地網(wǎng)段中的活躍主機。涉及內容包括:
- 圖形用戶界面:按鍵及監(jiān)聽、文本域、滾動條容器、安全更新文本域內容等;
- 簡單的跨平臺方法;
- 簡單的線程池應用方法;
代碼解讀
功能概述
1.界面設計:
- 程序包含一個文本域(JTextArea)用于顯示掃描結果。
- 有兩個按鈕:一個用于開始掃描,另一個用于退出程序。
2.掃描邏輯:
- 程序通過 ping 命令檢測本地網(wǎng)段中的活躍主機。
- 使用多線程(線程池)并發(fā)執(zhí)行掃描任務,提高掃描效率。
- 掃描完成后,結果顯示在文本域中。
3.跨平臺支持:
根據(jù)操作系統(tǒng)(Windows 或其他系統(tǒng))調整 ping 命令的格式。
代碼分解
界面部分
Container conn = getContentPane();//定義窗體容器
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設置默認窗體關閉
setBounds(300, 300, 400, 300);//設置窗體初始位置及大小
setTitle("內部網(wǎng)段掃描");//設置窗體標題
JScrollPane jScrollPane = new JScrollPane();//實例化滾動條容器
conn.add(jScrollPane, BorderLayout.CENTER);//向窗體容器中添加滾動條容器
scanner = new JTextArea();//實例化文本域
jScrollPane.setViewportView(scanner);//添加文本域對象到滾動條容器
JPanel jPanel = new JPanel();//實例化布局
conn.add(jPanel, BorderLayout.SOUTH);//將布局添加到窗體容器底部
startButt = new JButton("開始掃描...");//實例化開始掃描按鍵
jPanel.add(startButt);//將開始按鍵添加到布局
closeButt = new JButton("退 出");//實例化退出按鍵
jPanel.add(closeButt);//將退出按鍵添加到布局
其中:
實現(xiàn)掃描結果回顯到圖形界面
scanner = new JTextArea();//實例化文本域
jScrollPane.setViewportView(scanner);//添加文本域對象到滾動條容器
定義界面按鍵用以完成用戶交互
startButt = new JButton("開始掃描...");//實例化開始掃描按鍵
jPanel.add(startButt);//將開始按鍵添加到布局
??????? closeButt = new JButton("退 出");//實例化退出按鍵
jPanel.add(closeButt);//將退出按鍵添加到布局
功能部分
獲取本地網(wǎng)段
private String localIP() throws UnknownHostException {
InetAddress host = InetAddress.getLocalHost();//獲取本機網(wǎng)絡信息
String hostAddress = host.getHostAddress();//獲取本機ip地址
if (hostAddress == null) {//判斷本機是否聯(lián)網(wǎng)
return "網(wǎng)段獲取錯誤";
}
int pos = hostAddress.lastIndexOf(".");//指針移動到網(wǎng)段最后一個.上
return hostAddress.substring(0, pos + 1);//返回本機網(wǎng)段
}
通過 InetAddress.getLocalHost() 獲取本機 IP 地址。
提取 IP 地址的網(wǎng)段部分(例如,從 192.168.1.100 提取 192.168.1.)。
生成掃描命令【ping】
private String pingCommand() {
String os = System.getProperty("os.name").toLowerCase();//讀取系統(tǒng)平臺關鍵字,并且轉換為小寫
return os.contains("win") ? "cmd /c ping -n 1 -w 1000 " : "ping -c 1 -W 1 ";//根據(jù)系統(tǒng)平臺返回不同的ping命令
}
根據(jù)操作系統(tǒng)返回不同的 ping 命令格式
網(wǎng)段掃描【內部類】
class ScanerIp implements Runnable {
//定義類私有變量
private final String ip;//定義一個字符串用以存儲需要掃描的ip地址
public ScanerIp(String ip) {
this.ip = ip;//初始化ip地址
}
@Override
public void run() {
String command = pingCommand() + ip;//賦值ping命令
boolean isReachable = false;//判斷目的主機是否可達
try {
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream(), Charset.defaultCharset()));//創(chuàng)建一個緩存器,用以存儲命令結果
StringBuilder output = new StringBuilder();//建立一個命令執(zhí)行的輸出變量
String line;
while ((line = reader.readLine()) != null) {//逐行輸出命令結果
output.append(line).append("\n");
}
int exitCode = process.waitFor();//創(chuàng)建進程結束退出變量
String os = System.getProperty("os.name").toLowerCase();//獲取系統(tǒng)平臺信息
boolean isWindows = os.contains("win");//系統(tǒng)平臺為win時,變量為true
if (isWindows) {//判斷目的主機是否可達
isReachable = output.toString().contains("TTL=");
} else {
isReachable = (exitCode == 0);
}
} catch (Exception ex) {
ex.printStackTrace();
}
if (isReachable) {//目的主機可達時,更新文本域內容
SwingUtilities.invokeLater(() -> scanner.append(ip + "\n"));
}
}
}
每個 ScanerIp 實例負責掃描一個 IP 地址。
使用 Runtime.exec 執(zhí)行 ping 命令,并根據(jù)輸出判斷 IP 是否可達。
如果 IP 可達,通過 SwingUtilities.invokeLater 更新文本域,確保線程安全。
掃描按鈕監(jiān)聽
private class StartButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
startButt.setEnabled(false);//設置按鍵狀態(tài)為不可用
new Thread(() -> {
try {
String netSegment = localIP();//調用localIP()將本地網(wǎng)段給變量賦值
SwingUtilities.invokeLater(() -> {//更新文本域顯示內容
scanner.setText("開始掃描網(wǎng)段: " + netSegment + "0/24\n");
});
ExecutorService executor = Executors.newFixedThreadPool(20);//建立線程池
for (int i = 1; i <= 254; i++) {//逐個掃描本地網(wǎng)段
String ip = netSegment + i;
executor.execute(new ScanerIp(ip));
}
executor.shutdown();//關閉線程池
boolean finished = executor.awaitTermination(2, TimeUnit.MINUTES);//檢查線程是否超時
SwingUtilities.invokeLater(() -> {//更新文本域
scanner.append(finished ? "掃描完成!\n" : "掃描超時!\n");
startButt.setEnabled(true);//線程完成,按鍵恢復可用狀態(tài)
});
} catch (UnknownHostException ex) {
SwingUtilities.invokeLater(() -> {
scanner.append("無法獲取本地IP地址: " + ex.getMessage() + "\n");
startButt.setEnabled(true);
});
} catch (InterruptedException ex) {
SwingUtilities.invokeLater(() -> {
scanner.append("掃描被中斷\n");
startButt.setEnabled(true);
});
Thread.currentThread().interrupt();
}
}).start();
}
}點擊“開始掃描”按鈕后,程序獲取本地網(wǎng)段,并使用線程池并發(fā)掃描網(wǎng)段中的每個 IP 地址。
掃描完成后,更新文本域顯示掃描結果,并恢復按鈕狀態(tài)。
運行結果

完整代碼
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class TwentyTwoTestDemo00010002 extends JFrame {
//定義全局變量
private JTextArea scanner;//定義文本域
private JButton startButt;//定義開始掃描按鈕
private JButton closeButt;//定義退出按鈕
//類構造函數(shù),構造窗體
public TwentyTwoTestDemo00010002() {
Container conn = getContentPane();//定義窗體容器
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設置默認窗體關閉
setBounds(300, 300, 400, 300);//設置窗體初始位置及大小
setTitle("內部網(wǎng)段掃描");//設置窗體標題
JScrollPane jScrollPane = new JScrollPane();//實例化滾動條容器
conn.add(jScrollPane, BorderLayout.CENTER);//向窗體容器中添加滾動條容器
scanner = new JTextArea();//實例化文本域
jScrollPane.setViewportView(scanner);//添加文本域對象到滾動條容器
JPanel jPanel = new JPanel();//實例化布局
conn.add(jPanel, BorderLayout.SOUTH);//將布局添加到窗體容器底部
startButt = new JButton("開始掃描...");//實例化開始掃描按鍵
jPanel.add(startButt);//將開始按鍵添加到布局
closeButt = new JButton("退 出");//實例化退出按鍵
jPanel.add(closeButt);//將退出按鍵添加到布局
// 添加事件監(jiān)聽
startButt.addActionListener(new StartButtonListener());//添加開始掃描按鍵監(jiān)聽事件
closeButt.addActionListener(e -> System.exit(0));//添加退出按鍵退出功能
}
//獲取本地網(wǎng)段
private String localIP() throws UnknownHostException {
InetAddress host = InetAddress.getLocalHost();//獲取本機網(wǎng)絡信息
String hostAddress = host.getHostAddress();//獲取本機ip地址
if (hostAddress == null) {//判斷本機是否聯(lián)網(wǎng)
return "網(wǎng)段獲取錯誤";
}
int pos = hostAddress.lastIndexOf(".");//指針移動到網(wǎng)段最后一個.上
return hostAddress.substring(0, pos + 1);//返回本機網(wǎng)段
}
//檢測系統(tǒng)平臺
private String pingCommand() {
String os = System.getProperty("os.name").toLowerCase();//讀取系統(tǒng)平臺關鍵字,并且轉換為小寫
return os.contains("win") ? "cmd /c ping -n 1 -w 1000 " : "ping -c 1 -W 1 ";//根據(jù)系統(tǒng)平臺返回不同的ping命令
}
//網(wǎng)段掃描【內部類】
class ScanerIp implements Runnable {
//定義類私有變量
private final String ip;//定義一個字符串用以存儲需要掃描的ip地址
public ScanerIp(String ip) {
this.ip = ip;//初始化ip地址
}
@Override
public void run() {
String command = pingCommand() + ip;//賦值ping命令
boolean isReachable = false;//判斷目的主機是否可達
try {
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream(), Charset.defaultCharset()));//創(chuàng)建一個緩存器,用以存儲命令結果
StringBuilder output = new StringBuilder();//建立一個命令執(zhí)行的輸出變量
String line;
while ((line = reader.readLine()) != null) {//逐行輸出命令結果
output.append(line).append("\n");
}
int exitCode = process.waitFor();//創(chuàng)建進程結束退出變量
String os = System.getProperty("os.name").toLowerCase();//獲取系統(tǒng)平臺信息
boolean isWindows = os.contains("win");//系統(tǒng)平臺為win時,變量為true
if (isWindows) {//判斷目的主機是否可達
isReachable = output.toString().contains("TTL=");
} else {
isReachable = (exitCode == 0);
}
} catch (Exception ex) {
ex.printStackTrace();
}
if (isReachable) {//目的主機可達時,更新文本域內容
SwingUtilities.invokeLater(() -> scanner.append(ip + "\n"));
}
}
}
//建立按鍵監(jiān)聽方法
private class StartButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
startButt.setEnabled(false);//設置按鍵狀態(tài)為不可用
new Thread(() -> {
try {
String netSegment = localIP();//調用localIP()將本地網(wǎng)段給變量賦值
SwingUtilities.invokeLater(() -> {//更新文本域顯示內容
scanner.setText("開始掃描網(wǎng)段: " + netSegment + "0/24\n");
});
ExecutorService executor = Executors.newFixedThreadPool(20);//建立線程池
for (int i = 1; i <= 254; i++) {//逐個掃描本地網(wǎng)段
String ip = netSegment + i;
executor.execute(new ScanerIp(ip));
}
executor.shutdown();//關閉線程池
boolean finished = executor.awaitTermination(2, TimeUnit.MINUTES);//檢查線程是否超時
SwingUtilities.invokeLater(() -> {//更新文本域
scanner.append(finished ? "掃描完成!\n" : "掃描超時!\n");
startButt.setEnabled(true);//線程完成,按鍵恢復可用狀態(tài)
});
} catch (UnknownHostException ex) {
SwingUtilities.invokeLater(() -> {
scanner.append("無法獲取本地IP地址: " + ex.getMessage() + "\n");
startButt.setEnabled(true);
});
} catch (InterruptedException ex) {
SwingUtilities.invokeLater(() -> {
scanner.append("掃描被中斷\n");
startButt.setEnabled(true);
});
Thread.currentThread().interrupt();
}
}).start();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
TwentyTwoTestDemo00010002 frame = new TwentyTwoTestDemo00010002();
frame.setVisible(true);
});
}
}
到此這篇關于基于Java編寫一個簡單的內部網(wǎng)段掃描程序的文章就介紹到這了,更多相關Java內部網(wǎng)段掃描內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring Cloud Gateway 使用JWT工具類做用戶登錄校驗功能
這篇文章主要介紹了Spring Cloud Gateway 使用JWT工具類做用戶登錄校驗的示例代碼,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01
Mybatis generator修改Mapper.java文件實現(xiàn)詳解
這篇文章主要為大家介紹了Mybatis generator修改Mapper.java文件實現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09

