基于Java編寫一個簡單的內(nèi)部網(wǎng)段掃描程序
說明
這段代碼實現(xiàn)了一個簡單的內(nèi)部網(wǎng)段掃描工具,基于 Java Swing 構(gòu)建圖形用戶界面(GUI),并使用多線程來掃描本地網(wǎng)段中的活躍主機。涉及內(nèi)容包括:
- 圖形用戶界面:按鍵及監(jiān)聽、文本域、滾動條容器、安全更新文本域內(nèi)容等;
- 簡單的跨平臺方法;
- 簡單的線程池應(yīng)用方法;
代碼解讀
功能概述
1.界面設(shè)計:
- 程序包含一個文本域(JTextArea)用于顯示掃描結(jié)果。
- 有兩個按鈕:一個用于開始掃描,另一個用于退出程序。
2.掃描邏輯:
- 程序通過 ping 命令檢測本地網(wǎng)段中的活躍主機。
- 使用多線程(線程池)并發(fā)執(zhí)行掃描任務(wù),提高掃描效率。
- 掃描完成后,結(jié)果顯示在文本域中。
3.跨平臺支持:
根據(jù)操作系統(tǒng)(Windows 或其他系統(tǒng))調(diào)整 ping 命令的格式。
代碼分解
界面部分
Container conn = getContentPane();//定義窗體容器
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設(shè)置默認(rèn)窗體關(guān)閉
setBounds(300, 300, 400, 300);//設(shè)置窗體初始位置及大小
setTitle("內(nèi)部網(wǎng)段掃描");//設(shè)置窗體標(biāo)題
JScrollPane jScrollPane = new JScrollPane();//實例化滾動條容器
conn.add(jScrollPane, BorderLayout.CENTER);//向窗體容器中添加滾動條容器
scanner = new JTextArea();//實例化文本域
jScrollPane.setViewportView(scanner);//添加文本域?qū)ο蟮綕L動條容器
JPanel jPanel = new JPanel();//實例化布局
conn.add(jPanel, BorderLayout.SOUTH);//將布局添加到窗體容器底部
startButt = new JButton("開始掃描...");//實例化開始掃描按鍵
jPanel.add(startButt);//將開始按鍵添加到布局
closeButt = new JButton("退 出");//實例化退出按鍵
jPanel.add(closeButt);//將退出按鍵添加到布局
其中:
實現(xiàn)掃描結(jié)果回顯到圖形界面
scanner = new JTextArea();//實例化文本域
jScrollPane.setViewportView(scanner);//添加文本域?qū)ο蟮綕L動條容器
定義界面按鍵用以完成用戶交互
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)絡(luò)信息
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)平臺關(guān)鍵字,并且轉(zhuǎn)換為小寫
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)段掃描【內(nèi)部類】
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;//判斷目的主機是否可達(dá)
try {
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream(), Charset.defaultCharset()));//創(chuàng)建一個緩存器,用以存儲命令結(jié)果
StringBuilder output = new StringBuilder();//建立一個命令執(zhí)行的輸出變量
String line;
while ((line = reader.readLine()) != null) {//逐行輸出命令結(jié)果
output.append(line).append("\n");
}
int exitCode = process.waitFor();//創(chuàng)建進程結(jié)束退出變量
String os = System.getProperty("os.name").toLowerCase();//獲取系統(tǒng)平臺信息
boolean isWindows = os.contains("win");//系統(tǒng)平臺為win時,變量為true
if (isWindows) {//判斷目的主機是否可達(dá)
isReachable = output.toString().contains("TTL=");
} else {
isReachable = (exitCode == 0);
}
} catch (Exception ex) {
ex.printStackTrace();
}
if (isReachable) {//目的主機可達(dá)時,更新文本域內(nèi)容
SwingUtilities.invokeLater(() -> scanner.append(ip + "\n"));
}
}
}
每個 ScanerIp 實例負(fù)責(zé)掃描一個 IP 地址。
使用 Runtime.exec 執(zhí)行 ping 命令,并根據(jù)輸出判斷 IP 是否可達(dá)。
如果 IP 可達(dá),通過 SwingUtilities.invokeLater 更新文本域,確保線程安全。
掃描按鈕監(jiān)聽
private class StartButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
startButt.setEnabled(false);//設(shè)置按鍵狀態(tài)為不可用
new Thread(() -> {
try {
String netSegment = localIP();//調(diào)用localIP()將本地網(wǎng)段給變量賦值
SwingUtilities.invokeLater(() -> {//更新文本域顯示內(nèi)容
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();//關(guān)閉線程池
boolean finished = executor.awaitTermination(2, TimeUnit.MINUTES);//檢查線程是否超時
SwingUtilities.invokeLater(() -> {//更新文本域
scanner.append(finished ? "掃描完成!\n" : "掃描超時!\n");
startButt.setEnabled(true);//線程完成,按鍵恢復(fù)可用狀態(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 地址。
掃描完成后,更新文本域顯示掃描結(jié)果,并恢復(fù)按鈕狀態(tài)。
運行結(jié)果

完整代碼
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;//定義退出按鈕
//類構(gòu)造函數(shù),構(gòu)造窗體
public TwentyTwoTestDemo00010002() {
Container conn = getContentPane();//定義窗體容器
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設(shè)置默認(rèn)窗體關(guān)閉
setBounds(300, 300, 400, 300);//設(shè)置窗體初始位置及大小
setTitle("內(nèi)部網(wǎng)段掃描");//設(shè)置窗體標(biāo)題
JScrollPane jScrollPane = new JScrollPane();//實例化滾動條容器
conn.add(jScrollPane, BorderLayout.CENTER);//向窗體容器中添加滾動條容器
scanner = new JTextArea();//實例化文本域
jScrollPane.setViewportView(scanner);//添加文本域?qū)ο蟮綕L動條容器
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)絡(luò)信息
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)平臺關(guān)鍵字,并且轉(zhuǎn)換為小寫
return os.contains("win") ? "cmd /c ping -n 1 -w 1000 " : "ping -c 1 -W 1 ";//根據(jù)系統(tǒng)平臺返回不同的ping命令
}
//網(wǎng)段掃描【內(nèi)部類】
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;//判斷目的主機是否可達(dá)
try {
Process process = Runtime.getRuntime().exec(command);
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream(), Charset.defaultCharset()));//創(chuàng)建一個緩存器,用以存儲命令結(jié)果
StringBuilder output = new StringBuilder();//建立一個命令執(zhí)行的輸出變量
String line;
while ((line = reader.readLine()) != null) {//逐行輸出命令結(jié)果
output.append(line).append("\n");
}
int exitCode = process.waitFor();//創(chuàng)建進程結(jié)束退出變量
String os = System.getProperty("os.name").toLowerCase();//獲取系統(tǒng)平臺信息
boolean isWindows = os.contains("win");//系統(tǒng)平臺為win時,變量為true
if (isWindows) {//判斷目的主機是否可達(dá)
isReachable = output.toString().contains("TTL=");
} else {
isReachable = (exitCode == 0);
}
} catch (Exception ex) {
ex.printStackTrace();
}
if (isReachable) {//目的主機可達(dá)時,更新文本域內(nèi)容
SwingUtilities.invokeLater(() -> scanner.append(ip + "\n"));
}
}
}
//建立按鍵監(jiān)聽方法
private class StartButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
startButt.setEnabled(false);//設(shè)置按鍵狀態(tài)為不可用
new Thread(() -> {
try {
String netSegment = localIP();//調(diào)用localIP()將本地網(wǎng)段給變量賦值
SwingUtilities.invokeLater(() -> {//更新文本域顯示內(nèi)容
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();//關(guān)閉線程池
boolean finished = executor.awaitTermination(2, TimeUnit.MINUTES);//檢查線程是否超時
SwingUtilities.invokeLater(() -> {//更新文本域
scanner.append(finished ? "掃描完成!\n" : "掃描超時!\n");
startButt.setEnabled(true);//線程完成,按鍵恢復(fù)可用狀態(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);
});
}
}
到此這篇關(guān)于基于Java編寫一個簡單的內(nèi)部網(wǎng)段掃描程序的文章就介紹到這了,更多相關(guān)Java內(nèi)部網(wǎng)段掃描內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Cloud Gateway 使用JWT工具類做用戶登錄校驗功能
這篇文章主要介紹了Spring Cloud Gateway 使用JWT工具類做用戶登錄校驗的示例代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01
Mybatis generator修改Mapper.java文件實現(xiàn)詳解
這篇文章主要為大家介紹了Mybatis generator修改Mapper.java文件實現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09
java通過反射創(chuàng)建對象并調(diào)用方法
這篇文章主要介紹了java通過反射創(chuàng)建對象并調(diào)用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-01-01

