基于Java編寫一個簡單的內(nèi)部網(wǎng)段掃描程序
說明
這段代碼實現(xiàn)了一個簡單的內(nèi)部網(wǎng)段掃描工具,基于 Java Swing 構(gòu)建圖形用戶界面(GUI),并使用多線程來掃描本地網(wǎng)段中的活躍主機。涉及內(nèi)容包括:
- 圖形用戶界面:按鍵及監(jiān)聽、文本域、滾動條容器、安全更新文本域內(nèi)容等;
- 簡單的跨平臺方法;
- 簡單的線程池應用方法;
代碼解讀
功能概述
1.界面設(shè)計:
- 程序包含一個文本域(JTextArea)用于顯示掃描結(jié)果。
- 有兩個按鈕:一個用于開始掃描,另一個用于退出程序。
2.掃描邏輯:
- 程序通過 ping 命令檢測本地網(wǎng)段中的活躍主機。
- 使用多線程(線程池)并發(fā)執(zhí)行掃描任務,提高掃描效率。
- 掃描完成后,結(jié)果顯示在文本域中。
3.跨平臺支持:
根據(jù)操作系統(tǒng)(Windows 或其他系統(tǒng))調(diào)整 ping 命令的格式。
代碼分解
界面部分
Container conn = getContentPane();//定義窗體容器 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設(shè)置默認窗體關(guān)閉 setBounds(300, 300, 400, 300);//設(shè)置窗體初始位置及大小 setTitle("內(nèi)部網(wǎng)段掃描");//設(shè)置窗體標題 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)絡信息 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;//判斷目的主機是否可達 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) {//判斷目的主機是否可達 isReachable = output.toString().contains("TTL="); } else { isReachable = (exitCode == 0); } } catch (Exception ex) { ex.printStackTrace(); } if (isReachable) {//目的主機可達時,更新文本域內(nèi)容 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);//設(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);//線程完成,按鍵恢復可用狀態(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é)果,并恢復按鈕狀態(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è)置默認窗體關(guān)閉 setBounds(300, 300, 400, 300);//設(shè)置窗體初始位置及大小 setTitle("內(nèi)部網(wǎng)段掃描");//設(shè)置窗體標題 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)絡信息 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;//判斷目的主機是否可達 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) {//判斷目的主機是否可達 isReachable = output.toString().contains("TTL="); } else { isReachable = (exitCode == 0); } } catch (Exception ex) { ex.printStackTrace(); } if (isReachable) {//目的主機可達時,更新文本域內(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);//線程完成,按鍵恢復可用狀態(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)文章
SpringBoot集成Redis之配置、序列化與持久化方式
本文介紹了Redis的基本概念、常用數(shù)據(jù)類型及操作、SpringBoot整合Redis的方法、高級特性與安全性、性能優(yōu)化、測試與部署、數(shù)據(jù)一致性及版本更新等內(nèi)容,通過本文的學習,讀者可以掌握Redis的使用方法,并在實際項目中發(fā)揮其優(yōu)勢2024-11-11Java Scanner對象中hasNext()與next()方法的使用
這篇文章主要介紹了Java Scanner對象中hasNext()與next()方法的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10springboot如何使用logback-spring配置日志格式,并分環(huán)境配置
這篇文章主要介紹了springboot如何使用logback-spring配置日志格式,并分環(huán)境配置的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07MyBatis通過JDBC數(shù)據(jù)驅(qū)動生成的執(zhí)行語句問題
這篇文章主要介紹了MyBatis通過JDBC數(shù)據(jù)驅(qū)動生成的執(zhí)行語句問題的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-08-08