基于Java编写一个简单的内部网段扫描程序,
分享于 点击 584 次 点评:199
基于Java编写一个简单的内部网段扫描程序,
目录
- 说明
- 代码解读
- 功能概述
- 代码分解
- 运行结果
- 完整代码
说明
这段代码实现了一个简单的内部网段扫描工具,基于 Java Swing 构建图形用户界面(GUI),并使用多线程来扫描本地网段中的活跃主机。涉及内容包括:
- 图形用户界面:按键及监听、文本域、滚动条容器、安全更新文本域内容等;
- 简单的跨平台方法;
- 简单的线程池应用方法;
代码解读
功能概述
1.界面设计:
- 程序包含一个文本域(JTextArea)用于显示扫描结果。
- 有两个按钮:一个用于开始扫描,另一个用于退出程序。
2.扫描逻辑:
- 程序通过 ping 命令检测本地网段中的活跃主机。
- 使用多线程(线程池)并发执行扫描任务,提高扫描效率。
- 扫描完成后,结果显示在文本域中。
3.跨平台支持:
根据操作系统(Windows 或其他系统)调整 ping 命令的格式。
代码分解
界面部分
Container conn = getContentPane();//定义窗体容器 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置默认窗体关闭 setBounds(300, 300, 400, 300);//设置窗体初始位置及大小 setTitle("内部网段扫描");//设置窗体标题 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);//将退出按键添加到布局
其中:
实现扫描结果回显到图形界面
scanner = new JTextArea();//实例化文本域 jScrollPane.setViewportView(scanner);//添加文本域对象到滚动条容器
定义界面按键用以完成用户交互
startButt = new JButton("开始扫描...");//实例化开始扫描按键 jPanel.add(startButt);//将开始按键添加到布局 closeButt = new JButton("退 出");//实例化退出按键 jPanel.add(closeButt);//将退出按键添加到布局
功能部分
获取本地网段
private String localIP() throws UnknownHostException { InetAddress host = InetAddress.getLocalHost();//获取本机网络信息 String hostAddress = host.getHostAddress();//获取本机ip地址 if (hostAddress == null) {//判断本机是否联网 return "网段获取错误"; } int pos = hostAddress.lastIndexOf(".");//指针移动到网段最后一个.上 return hostAddress.substring(0, pos + 1);//返回本机网段 }
通过 InetAddress.getLocalHost() 获取本机 IP 地址。
提取 IP 地址的网段部分(例如,从 192.168.1.100 提取 192.168.1.)。
生成扫描命令【ping】
private String pingCommand() { String os = System.getProperty("os.name").toLowerCase();//读取系统平台关键字,并且转换为小写 return os.contains("win") ? "cmd /c ping -n 1 -w 1000 " : "ping -c 1 -W 1 ";//根据系统平台返回不同的ping命令 }
根据操作系统返回不同的 ping 命令格式
网段扫描【内部类】
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()));//创建一个缓存器,用以存储命令结果 StringBuilder output = new StringBuilder();//建立一个命令执行的输出变量 String line; while ((line = reader.readLine()) != null) {//逐行输出命令结果 output.append(line).append("\n"); } int exitCode = process.waitFor();//创建进程结束退出变量 String os = System.getProperty("os.name").toLowerCase();//获取系统平台信息 boolean isWindows = os.contains("win");//系统平台为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 执行 ping 命令,并根据输出判断 IP 是否可达。
如果 IP 可达,通过 SwingUtilities.invokeLater 更新文本域,确保线程安全。
扫描按钮监听
private class StartButtonListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { startButt.setEnabled(false);//设置按键状态为不可用 new Thread(() -> { try { String netSegment = localIP();//调用localIP()将本地网段给变量赋值 SwingUtilities.invokeLater(() -> {//更新文本域显示内容 scanner.setText("开始扫描网段: " + netSegment + "0/24\n"); }); ExecutorService executor = Executors.newFixedThreadPool(20);//建立线程池 for (int i = 1; i <= 254; i++) {//逐个扫描本地网段 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);//线程完成,按键恢复可用状态 }); } 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(); } }
点击“开始扫描”按钮后,程序获取本地网段,并使用线程池并发扫描网段中的每个 IP 地址。
扫描完成后,更新文本域显示扫描结果,并恢复按钮状态。
运行结果
完整代码
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;//定义退出按钮 //类构造函数,构造窗体 public TwentyTwoTestDemo00010002() { Container conn = getContentPane();//定义窗体容器 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置默认窗体关闭 setBounds(300, 300, 400, 300);//设置窗体初始位置及大小 setTitle("内部网段扫描");//设置窗体标题 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);//将退出按键添加到布局 // 添加事件监听 startButt.addActionListener(new StartButtonListener());//添加开始扫描按键监听事件 closeButt.addActionListener(e -> System.exit(0));//添加退出按键退出功能 } //获取本地网段 private String localIP() throws UnknownHostException { InetAddress host = InetAddress.getLocalHost();//获取本机网络信息 String hostAddress = host.getHostAddress();//获取本机ip地址 if (hostAddress == null) {//判断本机是否联网 return "网段获取错误"; } int pos = hostAddress.lastIndexOf(".");//指针移动到网段最后一个.上 return hostAddress.substring(0, pos + 1);//返回本机网段 } //检测系统平台 private String pingCommand() { String os = System.getProperty("os.name").toLowerCase();//读取系统平台关键字,并且转换为小写 return os.contains("win") ? "cmd /c ping -n 1 -w 1000 " : "ping -c 1 -W 1 ";//根据系统平台返回不同的ping命令 } //网段扫描【内部类】 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()));//创建一个缓存器,用以存储命令结果 StringBuilder output = new StringBuilder();//建立一个命令执行的输出变量 String line; while ((line = reader.readLine()) != null) {//逐行输出命令结果 output.append(line).append("\n"); } int exitCode = process.waitFor();//创建进程结束退出变量 String os = System.getProperty("os.name").toLowerCase();//获取系统平台信息 boolean isWindows = os.contains("win");//系统平台为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")); } } } //建立按键监听方法 private class StartButtonListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { startButt.setEnabled(false);//设置按键状态为不可用 new Thread(() -> { try { String netSegment = localIP();//调用localIP()将本地网段给变量赋值 SwingUtilities.invokeLater(() -> {//更新文本域显示内容 scanner.setText("开始扫描网段: " + netSegment + "0/24\n"); }); ExecutorService executor = Executors.newFixedThreadPool(20);//建立线程池 for (int i = 1; i <= 254; i++) {//逐个扫描本地网段 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);//线程完成,按键恢复可用状态 }); } 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编写一个简单的内部网段扫描程序的文章就介绍到这了,更多相关Java内部网段扫描内容请搜索3672js教程以前的文章或继续浏览下面的相关文章希望大家以后多多支持3672js教程!
您可能感兴趣的文章:- python实现扫描局域网指定网段ip的方法
- C#中实现网段扫描的代码
- java判断ip是否为指定网段示例
- java IP地址网段计算的示例代码
用户点评