java:多网卡环境下获取MAC地址

来源:互联网 发布:少女时代十周年知乎 编辑:程序博客网 时间:2024/06/17 02:21

JDK6以后 java.net.NetworkInterface提供了完整的方法用于获取网络设备信息。
调用 NetworkInterface.getNetworkInterfaces()可以返回所有网络设备
调用NetworkInterface.getHardwareAddress()就可以获取指定网卡的MAC.
下面的完整代码基于NetworkInterface提供了getNICs方法用于获取指定类型设备,通过指定不同的过滤器(Filter.UP,Filter.ALL…)的组合实现过滤条件订制。
提供getMacAddress方法用于获取指定设备的MAC地址

NetworkUtil.java

package net.gdface.facelog.device;import java.net.InetAddress;import java.net.NetworkInterface;import java.net.SocketException;import java.util.Iterator;import java.util.List;import java.util.Set;import com.google.common.collect.ImmutableSet;import com.google.common.collect.Iterators;import com.google.common.base.Predicates;import com.google.common.base.Joiner;import com.google.common.base.Predicate;import com.google.common.collect.Lists;import com.google.common.primitives.Bytes;import com.google.common.base.Function;/** * @author guyadong * */public class NetworkUtil {    public static enum Radix{        /** 二进制 */BIN(2),        /** 十进制 */DEC(10),        /** 十六进制 */HEX(16);        final int value;        Radix(int radix){            this.value = radix;        }    }    public static enum Filter implements Predicate<NetworkInterface>{        /** 过滤器: 所有网卡 */ALL,        /** 过滤器: 在线设备,see also {@link NetworkInterface#isUp()} */UP,        /** 过滤器: 虚拟接口,see also {@link NetworkInterface#isVirtual()} */VIRTUAL,        /** 过滤器:LOOPBACK, see also {@link NetworkInterface#isLoopback()} */LOOPBACK,        /** 过滤器:物理网卡 */PHYICAL_ONLY;        @Override        public boolean apply(NetworkInterface input) {            if(null == input ){                return false;            }            try{                byte[] hardwareAddress;                switch(this){                case UP:                    return input.isUp();                case VIRTUAL:                    return input.isVirtual();                case LOOPBACK:                    return input.isLoopback();                case PHYICAL_ONLY :                    hardwareAddress = input.getHardwareAddress();                    return null != hardwareAddress                             && hardwareAddress.length > 0                             && !input.isVirtual()                             && !isVMMac(hardwareAddress);                case ALL:                default :                    return true;                }            } catch (SocketException e) {                throw new RuntimeException(e);            }        }    }    /**     * 根据过滤器{@code filters}指定的条件(AND)返回网卡设备对象     * @param filters     * @return     */    @SafeVarargs    @SuppressWarnings("unchecked")    public static Set<NetworkInterface> getNICs(Predicate<NetworkInterface> ...filters) {        if(null == filters){            filters = new Predicate[]{Filter.ALL};        }        try {            Iterator<NetworkInterface> filtered = Iterators.filter(                    Iterators.forEnumeration(NetworkInterface.getNetworkInterfaces()),                    Predicates.and(filters));            return ImmutableSet.copyOf(filtered);        } catch (SocketException e) {            throw new RuntimeException(e);        }     }    /**     * 返回所有物理网卡     * @return     */    public static Set<NetworkInterface> getPhysicalNICs() {        return getNICs(Filter.PHYICAL_ONLY,Filter.UP);    }    /**     * 将{@code byte[]} 转换为{@code radix}指定格式的字符串     *      * @param source      * @param separator 分隔符     * @param radix 进制基数     * @return {@code source}为{@code null}时返回空字符串     */    public static final String format(byte[] source,String separator, final Radix radix) {        if (null == source){            return "";        }        if(null == separator){            separator = "";        }        List<String> hex = Lists.transform(Bytes.asList(source),new Function<Byte,String>(){            @Override            public String apply(Byte input) {                return String.copyValueOf(new char[]{                        Character.forDigit((input & 240) >> 4, radix.value),                        Character.forDigit(input & 15, radix.value)                });            }});        return Joiner.on(separator).join(hex);    }    /**      * MAC地址格式(16进制)格式化{@code source}指定的字节数组      * @see #format(byte[], String, int)     */    public static final String formatMac(byte[] source,String separator) {        return format(source,separator,Radix.HEX);    }    /**      * 以IP地址格式(点分位)格式化{@code source}指定的字节数组<br>     * @see #format(byte[], String, int)      */    public static final String formatIp(byte[] source) {        return format(source,".",Radix.DEC);    }    /**     * 返回指定{@code address}绑定的网卡的物理地址(MAC)     * @param address     * @return 指定的{@code address}没有绑定在任何网卡上返回{@code null}     * @see {@link NetworkInterface#getByInetAddress(InetAddress)}     * @see {@link NetworkInterface#getHardwareAddress()}     */    public static byte[] getMacAddress(InetAddress address) {        try {            NetworkInterface nic = NetworkInterface.getByInetAddress(address);            return null == nic ? null  : nic.getHardwareAddress();        } catch (SocketException e) {            throw new RuntimeException(e);        }    }    /**     * @param nic 网卡对象     * @param separator 格式化分隔符     * @return 表示MAC地址的字符串     */    public static String getMacAddress(NetworkInterface nic,String separator) {        try {            return format(nic.getHardwareAddress(),separator, Radix.HEX);        } catch (SocketException e) {            throw new RuntimeException(e);        }    }    /**     * 参见 {@link #getMacAddress(InetAddress)}     * @param address     * @param separator 格式化分隔符     * @return 表示MAC地址的字符串     */    public static String getMacAddress(InetAddress address,String separator) {        return format(getMacAddress(address),separator, Radix.HEX);         }    private static byte invalidMacs[][] = {            {0x00, 0x05, 0x69},             // VMWare            {0x00, 0x1C, 0x14},             // VMWare            {0x00, 0x0C, 0x29},             // VMWare            {0x00, 0x50, 0x56},             // VMWare            {0x08, 0x00, 0x27},             // Virtualbox            {0x0A, 0x00, 0x27},             // Virtualbox            {0x00, 0x03, (byte)0xFF},       // Virtual-PC            {0x00, 0x15, 0x5D}              // Hyper-V    };    private static boolean isVMMac(byte[] mac) {        if(null == mac) {            return false;        }        for (byte[] invalid: invalidMacs){            if (invalid[0] == mac[0] && invalid[1] == mac[1] && invalid[2] == mac[2]) {                return true;            }        }        return false;    }}
原创粉丝点击