1. 程式人生 > >java 當本地連線和無線網連結同時存在時,獲取目標IP同一網段的本地連結IP地址

java 當本地連線和無線網連結同時存在時,獲取目標IP同一網段的本地連結IP地址

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class NetUtil {

	public static void main(String[] args) {
		System.out.println(getLocalIp("192.168.1.1"));
	}

	/**
	 * 判斷目標IP是否和本地連結IP在同一網段
	 * 
	 * @param targetIp
	 * @return
	 */
	public static String getLocalIp(String targetIp) {
		// 獲取本地IP地址
		try {
			final Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
			boolean isTrueIp = false;
			if (allNetInterfaces != null) {

				List<String> addressList = new ArrayList<String>();
				// 用於存放IP和子網掩碼
				HashMap<String, String> map = new HashMap<String, String>();
				while (allNetInterfaces.hasMoreElements() && !isTrueIp) {
					final NetworkInterface netInterface = allNetInterfaces.nextElement();
					List<InterfaceAddress> interfaceAddressesList = netInterface.getInterfaceAddresses();
					if (interfaceAddressesList != null) {
						for (InterfaceAddress interfaceAddress : interfaceAddressesList) {
							InetAddress inetAddress = interfaceAddress.getAddress();
							if (inetAddress != null && inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) {
								// 獲取ip地址
								String hostAddress = inetAddress.getHostAddress();
								addressList.add(hostAddress);
								// 獲取子網掩碼
								String maskAddress = NetUtil.calcMaskByPrefixLength(interfaceAddress.getNetworkPrefixLength());
								// 將IP地址和子網掩碼存放到map中
								map.put(hostAddress, maskAddress);
							}
						}
					}
				}

				if (addressList.size() > 0) {
					// 算出匹配度最高的ip地址
					String matchedIp = NetUtil.matchMaxIp(addressList, targetIp);
					System.out.println("matchedIp   " + matchedIp);

					// 根據IP地址取出子網掩碼
					String matchedMask = map.get(matchedIp);
					if (matchedMask != null) {
						// 本地ip和子網掩碼按位與後的結果
						String subnetAddress = NetUtil.calcSubnetAddress(matchedIp, matchedMask);
						System.out.println("subnetAddress  " + subnetAddress);

						String subnetAddress2 = NetUtil.calcSubnetAddress(targetIp, matchedMask);
						if (subnetAddress.equals(subnetAddress2)) {
							return matchedIp;
						}
					}
				}
			}
		} catch (final SocketException e) {
			e.printStackTrace();
		}
		return null;

	}

	/**
	 * 計運算元網掩碼
	 * 
	 * @param length
	 * @return
	 */
	public static String calcMaskByPrefixLength(int length) {
		if (length == -1) {
			length = 24;
		}
		StringBuilder maskStr = new StringBuilder();
		int[] maskIp = new int[4];
		for (int i = 0; i < maskIp.length; i++) {
			maskIp[i] = (length >= 8) ? 255 : (length > 0 ? (0xff << (8 - length) & 0xff) : 0);
			length -= 8;
			maskStr.append(maskIp[i]);
			if (i < maskIp.length - 1) {
				maskStr.append(".");
			}
		}
		return maskStr.toString();
	}

	/**
	 * 計算ip地址和子網掩碼按位與結果
	 * 
	 * @param ip
	 * @param mask
	 * @return
	 */
	public static String calcSubnetAddress(String ip, String mask) {
		String result = "";
		try {
			// calc sub-net IP
			InetAddress ipAddress = InetAddress.getByName(ip);
			InetAddress maskAddress = InetAddress.getByName(mask);

			byte[] ipRaw = ipAddress.getAddress();
			byte[] maskRaw = maskAddress.getAddress();

			int unsignedByteFilter = 0x000000ff;
			int[] resultRaw = new int[ipRaw.length];
			for (int i = 0; i < resultRaw.length; i++) {
				resultRaw[i] = (ipRaw[i] & maskRaw[i] & unsignedByteFilter);
			}
			// make result string
			result = result + resultRaw[0];
			for (int i = 1; i < resultRaw.length; i++) {
				result = result + "." + resultRaw[i];
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * 算出匹配度最高的ip地址
	 * 
	 * @param addressList
	 * @param networkSegment
	 * @return
	 */
	public static String matchMaxIp(List<String> addressList, String networkSegment) {
		List<Integer> list = new ArrayList<Integer>();
		Map<Integer, String> hashMap = new HashMap<Integer, String>();

		StringBuilder sb = new StringBuilder();
		String[] split = networkSegment.split("\\.");
		for (String string : split) {
			String binaryString = Integer.toBinaryString(Integer.valueOf(string));
			while (binaryString.length() < 8) {
				binaryString = "0" + binaryString;
			}
			sb.append(binaryString);
		}

		for (String address : addressList) {
			if (address.equals(networkSegment)) {
				return address;
			}
			int match = match(address, sb.toString());
			list.add(match);
			hashMap.put(match, address);
		}
		Collections.sort(list);

		return hashMap.get(list.get(list.size() - 1));
	}

	/**
	 * 計算ip地址的匹配度
	 * 
	 * @param address
	 * @param networkSegment
	 * @return
	 */
	public static int match(String address, String networkSegment) {
		int length = 0;
		String[] split = address.split("\\.");
		StringBuilder sb1 = new StringBuilder();

		for (String string : split) {
			String binaryString = Integer.toBinaryString(Integer.valueOf(string));
			while (binaryString.length() < 8) {
				binaryString = "0" + binaryString;
			}
			sb1.append(binaryString);
		}
		for (int i = 0; i < sb1.length(); i++) {
			if (sb1.charAt(i) == networkSegment.charAt(i)) {
				length++;
			} else {
				return length;
			}
		}
		return length;
	}
}