【转】java:多网卡环境下获取MAC地址
http://blog.csdn.net/10km/article/details/78569962
JDK6以后 java.net.NetworkInterface
提供了完整的方法用于获取网络设备信息。
调用 NetworkInterface.getNetworkInterfaces()
可以返回所有网络设备
调用NetworkInterface.getHardwareAddress()
就可以获取指定网卡的MAC.
下面的完整代码基于NetworkInterface提供了getNICs方法用于获取指定类型设备,通过指定不同的过滤器(Filter.UP,Filter.ALL…)的组合实现过滤条件订制。
提供getMacAddress方法用于获取指定设备的MAC地址
NetworkUtil.java
1 package net.gdface.facelog.device; 2 3 import java.net.InetAddress; 4 import java.net.NetworkInterface; 5 import java.net.SocketException; 6 import java.util.Iterator; 7 import java.util.List; 8 import java.util.Set; 9 10 import com.google.common.collect.ImmutableSet; 11 import com.google.common.collect.Iterators; 12 13 import com.google.common.base.Predicates; 14 15 import com.google.common.base.Joiner; 16 import com.google.common.base.Predicate; 17 import com.google.common.collect.Lists; 18 import com.google.common.primitives.Bytes; 19 20 import com.google.common.base.Function; 21 22 /** 23 * @author guyadong 24 * 25 */ 26 public class NetworkUtil { 27 public static enum Radix{ 28 /** 二进制 */BIN(2), 29 /** 十进制 */DEC(10), 30 /** 十六进制 */HEX(16); 31 final int value; 32 Radix(int radix){ 33 this.value = radix; 34 } 35 } 36 public static enum Filter implements Predicate<NetworkInterface>{ 37 /** 过滤器: 所有网卡 */ALL, 38 /** 过滤器: 在线设备,see also {@link NetworkInterface#isUp()} */UP, 39 /** 过滤器: 虚拟接口,see also {@link NetworkInterface#isVirtual()} */VIRTUAL, 40 /** 过滤器:LOOPBACK, see also {@link NetworkInterface#isLoopback()} */LOOPBACK, 41 /** 过滤器:物理网卡 */PHYICAL_ONLY; 42 43 @Override 44 public boolean apply(NetworkInterface input) { 45 if(null == input ){ 46 return false; 47 } 48 try{ 49 byte[] hardwareAddress; 50 switch(this){ 51 case UP: 52 return input.isUp(); 53 case VIRTUAL: 54 return input.isVirtual(); 55 case LOOPBACK: 56 return input.isLoopback(); 57 case PHYICAL_ONLY : 58 hardwareAddress = input.getHardwareAddress(); 59 return null != hardwareAddress 60 && hardwareAddress.length > 0 61 && !input.isVirtual() 62 && !isVMMac(hardwareAddress); 63 case ALL: 64 default : 65 return true; 66 } 67 } catch (SocketException e) { 68 throw new RuntimeException(e); 69 } 70 } 71 } 72 /** 73 * 根据过滤器{@code filters}指定的条件(AND)返回网卡设备对象 74 * @param filters 75 * @return 76 */ 77 @SafeVarargs 78 @SuppressWarnings("unchecked") 79 public static Set<NetworkInterface> getNICs(Predicate<NetworkInterface> ...filters) { 80 if(null == filters){ 81 filters = new Predicate[]{Filter.ALL}; 82 } 83 try { 84 Iterator<NetworkInterface> filtered = Iterators.filter( 85 Iterators.forEnumeration(NetworkInterface.getNetworkInterfaces()), 86 Predicates.and(filters)); 87 return ImmutableSet.copyOf(filtered); 88 } catch (SocketException e) { 89 throw new RuntimeException(e); 90 } 91 } 92 /** 93 * 返回所有物理网卡 94 * @return 95 */ 96 public static Set<NetworkInterface> getPhysicalNICs() { 97 return getNICs(Filter.PHYICAL_ONLY,Filter.UP); 98 } 99 /** 100 * 将{@code byte[]} 转换为{@code radix}指定格式的字符串 101 * 102 * @param source 103 * @param separator 分隔符 104 * @param radix 进制基数 105 * @return {@code source}为{@code null}时返回空字符串 106 */ 107 public static final String format(byte[] source,String separator, final Radix radix) { 108 if (null == source){ 109 return ""; 110 } 111 if(null == separator){ 112 separator = ""; 113 } 114 List<String> hex = Lists.transform(Bytes.asList(source),new Function<Byte,String>(){ 115 @Override 116 public String apply(Byte input) { 117 return String.copyValueOf(new char[]{ 118 Character.forDigit((input & 240) >> 4, radix.value), 119 Character.forDigit(input & 15, radix.value) 120 }); 121 }}); 122 return Joiner.on(separator).join(hex); 123 } 124 /** 125 * MAC地址格式(16进制)格式化{@code source}指定的字节数组 126 * @see #format(byte[], String, int) 127 */ 128 public static final String formatMac(byte[] source,String separator) { 129 return format(source,separator,Radix.HEX); 130 } 131 /** 132 * 以IP地址格式(点分位)格式化{@code source}指定的字节数组<br> 133 * @see #format(byte[], String, int) 134 */ 135 public static final String formatIp(byte[] source) { 136 return format(source,".",Radix.DEC); 137 } 138 /** 139 * 返回指定{@code address}绑定的网卡的物理地址(MAC) 140 * @param address 141 * @return 指定的{@code address}没有绑定在任何网卡上返回{@code null} 142 * @see {@link NetworkInterface#getByInetAddress(InetAddress)} 143 * @see {@link NetworkInterface#getHardwareAddress()} 144 */ 145 public static byte[] getMacAddress(InetAddress address) { 146 try { 147 NetworkInterface nic = NetworkInterface.getByInetAddress(address); 148 return null == nic ? null : nic.getHardwareAddress(); 149 } catch (SocketException e) { 150 throw new RuntimeException(e); 151 } 152 } 153 /** 154 * @param nic 网卡对象 155 * @param separator 格式化分隔符 156 * @return 表示MAC地址的字符串 157 */ 158 public static String getMacAddress(NetworkInterface nic,String separator) { 159 try { 160 return format(nic.getHardwareAddress(),separator, Radix.HEX); 161 } catch (SocketException e) { 162 throw new RuntimeException(e); 163 } 164 } 165 /** 166 * 参见 {@link #getMacAddress(InetAddress)} 167 * @param address 168 * @param separator 格式化分隔符 169 * @return 表示MAC地址的字符串 170 */ 171 public static String getMacAddress(InetAddress address,String separator) { 172 return format(getMacAddress(address),separator, Radix.HEX); 173 } 174 private static byte invalidMacs[][] = { 175 {0x00, 0x05, 0x69}, // VMWare 176 {0x00, 0x1C, 0x14}, // VMWare 177 {0x00, 0x0C, 0x29}, // VMWare 178 {0x00, 0x50, 0x56}, // VMWare 179 {0x08, 0x00, 0x27}, // Virtualbox 180 {0x0A, 0x00, 0x27}, // Virtualbox 181 {0x00, 0x03, (byte)0xFF}, // Virtual-PC 182 {0x00, 0x15, 0x5D} // Hyper-V 183 }; 184 private static boolean isVMMac(byte[] mac) { 185 if(null == mac) { 186 return false; 187 } 188 189 for (byte[] invalid: invalidMacs){ 190 if (invalid[0] == mac[0] && invalid[1] == mac[1] && invalid[2] == mac[2]) { 191 return true; 192 } 193 } 194 195 return false; 196 } 197 198 }