局域网下扫描占用的 ip java版 2022-01-19 程序之旅 暂无评论 631 次阅读 ## 局域网下扫描占用的 ip java版 需求是通过自身的局域网 ip,找到子网掩码为 255.255.255.0 的已经被占用的ip,为了调高扫描的效率,需要多线程进行扫描。 ```java import info.mufeng.hardware.model.PingResult; import lombok.Synchronized; import lombok.extern.slf4j.Slf4j; import org.springframework.lang.Nullable; import java.io.IOException; import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask; import java.util.regex.Pattern; @Slf4j public class HostIpUtils { public static Map PING_RESULT_MAP = new ConcurrentHashMap<>(); // ping 超时时间,默认 200 ms public static final Integer PING_TIME_OUT = 200; /** * 检查 ip 的状态 * * @param ipAddress * @param second * @Method checkIpStatus * @Author liurui * @Date 2022/1/18 17:33 * @Return boolean */ public static boolean checkIpStatus(String ipAddress, int second) throws IOException, InterruptedException { long start = System.currentTimeMillis(); String infomand = "ping -n 1 -w " + second + " " + ipAddress; int wait = Runtime.getRuntime().exec(infomand).waitFor(); log.info("等待结果 {},{}, 等待时间:{}", ipAddress, wait, System.currentTimeMillis() - start + "ms"); return 0 == wait; } public static List getLocalIpList() throws SocketException { List ipList = new ArrayList(); InetAddress ip = null; Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); while (networkInterfaces.hasMoreElements()) { NetworkInterface ni = networkInterfaces.nextElement(); Enumeration ips = ni.getInetAddresses(); while (ips.hasMoreElements()) { ip = ips.nextElement(); if (ip == null || ip.getHostAddress() == null) { continue; } String sip = ip.getHostAddress(); ipList.add(sip); } } return ipList; } /** * 提取 ipv4 的可用 ip * * @param ipList * @Method extractIpV4 * @Author liurui * @Date 2022/1/19 9:59 * @Return java.util.List */ public static List extractIpV4(List ipList) { String regex = "^(((\\d{1,2})|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))\\.){3}((\\d{1,2})|(1\\d{2})|(2[0-4]\\d)|(25[0-5]))$"; Pattern pattern = Pattern.infopile(regex); for (Iterator ite = ipList.iterator(); ite.hasNext(); ) { String ip = ite.next(); if (!pattern.matcher(ip).matches() || "127.0.0.1".equals(ip) || ip.endsWith(".1")) { // 移除 ite.remove(); } } return ipList; } /** * 扫描所有的可用 ip * * @param ip * @Method scanUsedIp * @Author liurui * @Date 2022/1/19 9:29 * @Return java.util.List */ public static List scanUsedIp(String ip) { ForkJoinPool pool = new ForkJoinPool(); // 当前网段的 ip String[] makeIp = makeIp(ip); PingIpTask innerFind = new PingIpTask(makeIp, 0, makeIp.length - 1); pool.invoke(innerFind); // 同步调用 List pingResults = innerFind.join(); // 缓存可用的 ip cacheUsedIp(pingResults); return pingResults; } private static class PingIpTask extends RecursiveTask> { // 处理的数据分成10份 private int threshold; private String[] ips; // 表示我们要实际ping的数组 private int fromIndex; // 开始ping的下标 private int toIndex; // 到哪里结束的下标 /** * 被使用的 ip */ private List usedipList = new ArrayList<>(); public PingIpTask(String[] ips, int fromIndex, int toIndex) { this.ips = ips; this.fromIndex = fromIndex; this.toIndex = toIndex; this.threshold = ips.length / 10; } public List getUsedipList() { return usedipList; } @Override protected List infopute() { if (toIndex - fromIndex < threshold) { for (int i = fromIndex; i <= toIndex; i++) { String ip = ips[i]; try { PingResult pingResult = pingIp(ip); if (pingResult != null && pingResult.isStatus()) { usedipList.add(pingResult); } } catch (Exception e) { log.error("ping ip 错误{}", ip, e); e.printStackTrace(); } } } else { int mid = (fromIndex + toIndex) / 2; PingIpTask left = new PingIpTask(ips, fromIndex, mid); PingIpTask right = new PingIpTask(ips, mid + 1, toIndex); invokeAll(left, right); usedipList.addAll(left.getUsedipList()); usedipList.addAll(right.getUsedipList()); } return usedipList; } } /** * 缓存可用 ip * * @param pingResultList * @Method cacheUsedIp * @Author liurui * @Date 2022/1/19 9:09 * @Return void */ @Synchronized public static void cacheUsedIp(List pingResultList) { PING_RESULT_MAP.clear(); pingResultList.stream().forEach(pingResult -> PING_RESULT_MAP.put(pingResult.getAddress(), pingResult)); } /** * 生成 ip * * @param ip * @Method makeIp * @Author liurui * @Date 2022/1/18 19:36 * @Return java.lang.String[] */ public static String[] makeIp(String ip) { int lastPointIndex = ip.lastIndexOf('.'); String ipHead = ip.substring(0, ++lastPointIndex); List ipList = new ArrayList<>(); for (int i = 2; i <= 255; i++) { ipList.add(ipHead + i); } return ipList.toArray(new String[ipList.size()]); } /** * 获取 ip 信息 * * @param ip * @Method pingIp * @Author liurui * @Date 2022/1/18 17:54 * @Return info.mufeng.hardware.model.PingResult */ @Nullable public static PingResult pingIp(String ip) throws IOException, InterruptedException { boolean status = checkIpStatus(ip, PING_TIME_OUT); if (!status) { return null; } PingResult result = new PingResult(); InetAddress inetAddress = InetAddress.getByName(ip); log.info("================"); log.info("主机名称: " + inetAddress.getHostName()); log.info("主机地址:" + inetAddress.getHostAddress()); result.setAddress(inetAddress.getHostAddress()); result.setHostName(inetAddress.getHostName()); return result; } public static void main(String[] args) throws IOException, InterruptedException { long start = System.currentTimeMillis(); String ip = "192.168.21.50"; // 2022/1/19 liurui 获取当前所有网卡的ip List localIpList = getLocalIpList(); List filterIpV4 = extractIpV4(localIpList); for (String o : filterIpV4) { System.out.println(o); } } } ``` 执行扫描,发现执行效率还是比较慢,大概一轮下来需要花 2分钟,后续继续探寻还有什么其他好的办法。 打赏: 微信, 支付宝 标签: java 本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。