001package net.gdface.utils; 002import java.io.BufferedReader; 003import java.io.IOException; 004import java.io.InputStream; 005import java.io.InputStreamReader; 006import java.net.HttpURLConnection; 007import java.net.InetAddress; 008import java.net.NetworkInterface; 009import java.net.Socket; 010import java.net.SocketException; 011import java.net.URL; 012import java.net.UnknownHostException; 013import java.util.Iterator; 014import java.util.List; 015import java.util.Set; 016 017import static com.google.common.base.Preconditions.*; 018 019import com.google.common.collect.ImmutableSet; 020import com.google.common.collect.Iterators; 021 022import com.google.common.base.Predicates; 023 024import com.google.common.base.Joiner; 025import com.google.common.base.MoreObjects; 026import com.google.common.base.Predicate; 027import com.google.common.collect.Lists; 028import com.google.common.primitives.Bytes; 029 030import com.google.common.base.Function; 031 032/** 033 * 网络管ç†å·¥å…·ç±» 034 * @author guyadong 035 * @since 1.0.7 036 * 037 */ 038public class NetworkUtil { 039 public static final String DEFAULT_HOST = "localhost"; 040 public static enum Radix{ 041 /** 二进制 */BIN(2), 042 /** å进制 */DEC(10), 043 /** åå…进制 */HEX(16); 044 public final int value; 045 Radix(int radix){ 046 this.value = radix; 047 } 048 } 049 public static enum Filter implements Predicate<NetworkInterface>{ 050 /** 过滤器: æ‰€æœ‰ç½‘å¡ */ALL, 051 /** 过滤器: 在线设备,see also {@link NetworkInterface#isUp()} */UP, 052 /** 过滤器: 虚拟接å£,see also {@link NetworkInterface#isVirtual()} */VIRTUAL, 053 /** 过滤器:LOOPBACK, see also {@link NetworkInterface#isLoopback()} */LOOPBACK, 054 /** 过滤器:物ç†ç½‘å¡ */PHYICAL_ONLY; 055 056 @Override 057 public boolean apply(NetworkInterface input) { 058 if(null == input ){ 059 return false; 060 } 061 try{ 062 switch(this){ 063 case UP: 064 return input.isUp(); 065 case VIRTUAL: 066 return input.isVirtual(); 067 case LOOPBACK: 068 return input.isLoopback(); 069 case PHYICAL_ONLY :{ 070 byte[] hardwareAddress = input.getHardwareAddress(); 071 return null != hardwareAddress 072 && hardwareAddress.length > 0 073 && !input.isVirtual() 074 && !isVMMac(hardwareAddress); 075 } 076 case ALL: 077 default : 078 return true; 079 } 080 } catch (SocketException e) { 081 throw new RuntimeException(e); 082 } 083 } 084 } 085 /** 086 * æ ¹æ®è¿‡æ»¤å™¨{@code filters}指定的æ¡ä»¶(AND)返回网å¡è®¾å¤‡å¯¹è±¡ 087 * @param filters 088 * @return 089 */ 090 @SafeVarargs 091 @SuppressWarnings("unchecked") 092 public static Set<NetworkInterface> getNICs(Predicate<NetworkInterface> ...filters) { 093 if(null == filters){ 094 filters = new Predicate[]{Filter.ALL}; 095 } 096 try { 097 Iterator<NetworkInterface> filtered = Iterators.filter( 098 Iterators.forEnumeration(NetworkInterface.getNetworkInterfaces()), 099 Predicates.and(filters)); 100 return ImmutableSet.copyOf(filtered); 101 } catch (SocketException e) { 102 throw new RuntimeException(e); 103 } 104 } 105 /** 106 * 返回所有物ç†ç½‘å¡ 107 * @return 108 */ 109 public static Set<NetworkInterface> getPhysicalNICs() { 110 return getNICs(Filter.PHYICAL_ONLY,Filter.UP); 111 } 112 /** 113 * å°†{@code byte[]} 转æ¢ä¸º{@code radix}æŒ‡å®šæ ¼å¼çš„å—符串 114 * 115 * @param source 116 * @param separator 分隔符 117 * @param radix 进制基数 118 * @return {@code source}为{@code null}时返回空å—符串 119 */ 120 public static final String format(byte[] source,String separator, final Radix radix) { 121 if (null == source){ 122 return ""; 123 } 124 if(null == separator){ 125 separator = ""; 126 } 127 List<String> hex = Lists.transform(Bytes.asList(source),new Function<Byte,String>(){ 128 @Override 129 public String apply(Byte input) { 130 switch (radix) { 131 case HEX: 132 return String.format("%02x", input & 0xff); 133 default: 134 return Integer.toString(input & 0xff, radix.value); 135 } 136 }}); 137 return Joiner.on(separator).join(hex); 138 } 139 /** 140 * MACåœ°å€æ ¼å¼(16进制)æ ¼å¼åŒ–{@code source}指定的å—节数组 141 * @see #format(byte[], String, Radix) 142 */ 143 public static final String formatMac(byte[] source,String separator) { 144 return format(source,separator,Radix.HEX); 145 } 146 /** 147 * 以IPåœ°å€æ ¼å¼(点分ä½)æ ¼å¼åŒ–{@code source}指定的å—节数组<br> 148 * @see #format(byte[], String, Radix) 149 */ 150 public static final String formatIp(byte[] source) { 151 return format(source,".",Radix.DEC); 152 } 153 /** 154 * 返回指定{@code address}绑定的网å¡çš„物ç†åœ°å€(MAC) 155 * @param address 156 * @return 指定的{@code address}没有绑定在任何网å¡ä¸Šè¿”回{@code null} 157 * @see NetworkInterface#getByInetAddress(InetAddress) 158 * @see NetworkInterface#getHardwareAddress() 159 */ 160 public static byte[] getMacAddress(InetAddress address) { 161 try { 162 NetworkInterface nic = NetworkInterface.getByInetAddress(address); 163 return null == nic ? null : nic.getHardwareAddress(); 164 } catch (SocketException e) { 165 throw new RuntimeException(e); 166 } 167 } 168 /** 169 * @param nic 网å¡å¯¹è±¡ 170 * @param separator æ ¼å¼åŒ–分隔符 171 * @return 表示MAC地å€çš„å—符串 172 */ 173 public static String getMacAddress(NetworkInterface nic,String separator) { 174 try { 175 return format(nic.getHardwareAddress(),separator, Radix.HEX); 176 } catch (SocketException e) { 177 throw new RuntimeException(e); 178 } 179 } 180 /** 181 * å‚è§ {@link #getMacAddress(InetAddress)} 182 * @param address 183 * @param separator æ ¼å¼åŒ–分隔符 184 * @return 表示MAC地å€çš„å—符串 185 */ 186 public static String getMacAddress(InetAddress address,String separator) { 187 return format(getMacAddress(address),separator, Radix.HEX); 188 } 189 private static byte invalidMacs[][] = { 190 /** VMWare */{0x00, 0x05, 0x69}, 191 /** VMWare */{0x00, 0x1C, 0x14}, 192 /** VMWare */{0x00, 0x0C, 0x29}, 193 /** VMWare */{0x00, 0x50, 0x56}, 194 /** Virtualbox */{0x08, 0x00, 0x27}, 195 /** Virtualbox */{0x0A, 0x00, 0x27}, 196 /** Virtual-PC */{0x00, 0x03, (byte)0xFF}, 197 /** Hyper-V */{0x00, 0x15, 0x5D} 198 }; 199 private static boolean isVMMac(byte[] mac) { 200 if(null == mac) { 201 return false; 202 } 203 204 for (byte[] invalid: invalidMacs){ 205 if (invalid[0] == mac[0] && invalid[1] == mac[1] && invalid[2] == mac[2]) { 206 return true; 207 } 208 } 209 return false; 210 } 211 /** 判æ–{@code host}是å¦ä¸ºlocalhost */ 212 public static final boolean isLoopbackAddress(String host) { 213 return "127.0.0.1".equals(host) 214 || "::1".equals(host) 215 || DEFAULT_HOST.equals(host); 216 } 217 /** 判æ–{@code address}是å¦ä¸ºæœ¬æœºåœ°å€ */ 218 public static final boolean isLocalhost(InetAddress address) { 219 try { 220 return address.isLoopbackAddress() 221 || InetAddress.getLocalHost().getHostAddress().equals( address.getHostAddress()) ; 222 } catch (UnknownHostException e) { 223 throw new RuntimeException(e); 224 } 225 } 226 /** 判æ–{@code address}是å¦ä¸ºæœ¬æœºåœ°å€ */ 227 public static final boolean isLocalhost(String host) { 228 try { 229 return isLoopbackAddress(host) || isLocalhost(InetAddress.getByName(checkNotNull(host))); 230 } catch (UnknownHostException e) { 231 return false; 232 } 233 } 234 /** 如果{@code host}为localhost转æ¢ä¸º{@value #DEFAULT_HOST} */ 235 public static final String convertHost(String host) { 236 return isLoopbackAddress(host)? DEFAULT_HOST : host; 237 } 238 239 /** é历所有物ç†ç½‘上绑定的地å€,判æ–{@code address}是å¦ä¸ºæœ¬æœºç½‘å¡ç»‘å®šçš„åœ°å€ */ 240 public static boolean selfBind(final InetAddress address){ 241 if(isLocalhost(address)){ 242 return true; 243 } 244 final Predicate<InetAddress> filter = new Predicate<InetAddress>(){ 245 @Override 246 public boolean apply(InetAddress input) { 247 return input.getHostAddress().equals(address.getHostAddress()); 248 }}; 249 return Iterators.tryFind(getPhysicalNICs().iterator(),new Predicate<NetworkInterface>(){ 250 @Override 251 public boolean apply(NetworkInterface input) { 252 return Iterators.tryFind( 253 Iterators.forEnumeration(input.getInetAddresses()), 254 filter).isPresent(); 255 }}).isPresent(); 256 } 257 /** see also {@link #selfBind(InetAddress)} */ 258 public static boolean selfBind(String host){ 259 try { 260 return selfBind(InetAddress.getByName(host)); 261 } catch (UnknownHostException e) { 262 return false; 263 } 264 } 265 /** 266 * 获å–访问指定host的当å‰ç½‘å¡ç‰©ç†åœ°å€ 267 * @param host 268 * @param port 269 * @return 270 * @throws IOException 271 */ 272 public static byte[] getCurrentMac(String host,int port) throws IOException { 273 Socket socket = null; 274 try { 275 socket = new Socket(host,port); 276 InetAddress address = socket.getLocalAddress(); 277 NetworkInterface nic = NetworkInterface.getByInetAddress(address); 278 return nic.getHardwareAddress(); 279 } finally{ 280 if(socket != null){ 281 socket.close(); 282 } 283 } 284 } 285 /** 286 * 呿Œ‡å®šçš„urlå‘é€http请求 287 * @param url 288 * @param requestType 请求类型,see {@link HttpURLConnection#setRequestMethod(String)} 289 * @return 返回å“应数æ®ï¼Œè¯·æ±‚失败返回{@code null} 290 */ 291 public static String sendHttpRequest(URL url,String requestType) { 292 293 HttpURLConnection con = null; 294 295 BufferedReader buffer = null; 296 StringBuffer resultBuffer = null; 297 298 try { 299 //得到连接对象 300 con = (HttpURLConnection) url.openConnection(); 301 //设置请求类型 302 con.setRequestMethod(requestType); 303 //设置请求需è¦è¿”回的数æ®ç±»åž‹å’Œå—符集类型 304 con.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); 305 //å…许写出 306 con.setDoOutput(true); 307 //å…许读入 308 con.setDoInput(true); 309 //ä¸ä½¿ç”¨ç¼“å˜ 310 con.setUseCaches(false); 311 //得到å“应ç 312 int responseCode = con.getResponseCode(); 313 314 if(responseCode == HttpURLConnection.HTTP_OK){ 315 //得到å“åº”æµ 316 InputStream inputStream = con.getInputStream(); 317 //å°†å“应æµè½¬æ¢æˆå—符串 318 resultBuffer = new StringBuffer(); 319 String line; 320 buffer = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); 321 while ((line = buffer.readLine()) != null) { 322 resultBuffer.append(line); 323 } 324 return resultBuffer.toString(); 325 } 326 327 }catch(Exception e) { 328 }finally { 329 if (con != null){ 330 con.disconnect(); 331 } 332 } 333 return null; 334 } 335 /** 336 * è¿žæŽ¥æµ‹è¯•è¿”å›žçŠ¶æ€ 337 * @author guyadong 338 * 339 */ 340 public static enum ConnectStatus{ 341 /** å¯è¿žæŽ¥,httpå“应有效 */CONNECTABLE, 342 /** å¯è¿žæŽ¥,httpå“åº”æ— æ•ˆ */INVALID_RESPONE, 343 /** 连接失败 */FAIL 344 } 345 /** 346 * 测试http连接是å¦å¯è¿žæŽ¥<br> 347 * 连接失败返回{@link ConnectStatus#FAIL}, 348 * 建立连接åŽç”¨ 349 * {@code responseValidator}验è¯å“应数æ®ï¼Œ{@code responseValidator}返回{@code true}则连接有效返回{@link ConnectStatus#CONNECTABLE}, 350 * {@code responseValidator}返回{@code false}åˆ™è¿žæŽ¥æ— æ•ˆè¿”å›ž{@link ConnectStatus#INVALID_RESPONE} , 351 * 352 * @param url 测试的url 353 * @param responseValidator 用于验è¯å“åº”æ•°æ®æ˜¯å¦æœ‰æ•ˆçš„验è¯å™¨, 354 * 为{@code null}æ—¶,åªè¦è¿žæŽ¥æˆåŠŸå°±è¿”å›ž{@link ConnectStatus#CONNECTABLE} 355 * @return 连接状æ€{@link ConnectStatus} 356 */ 357 public static ConnectStatus testHttpConnect(URL url,Predicate<String> responseValidator){ 358 String reponse = sendHttpRequest(url,"GET"); 359 responseValidator = MoreObjects.firstNonNull(responseValidator, Predicates.<String>alwaysTrue()); 360 return reponse == null 361 ? ConnectStatus.FAIL : 362 (responseValidator.apply(reponse) 363 ? ConnectStatus.CONNECTABLE : ConnectStatus.INVALID_RESPONE); 364 } 365 /** 366 * 测试http连接是å¦å¯è¿žæŽ¥ 367 * @param url 测试的url 368 * @param responseValidator 369 * @return 连接状æ€{@link ConnectStatus} 370 * @see #testHttpConnect(URL, Predicate) 371 */ 372 public static ConnectStatus testHttpConnect(String url,Predicate<String> responseValidator){ 373 try { 374 return testHttpConnect(new URL(url),responseValidator); 375 } catch (Exception e) { 376 return ConnectStatus.FAIL; 377 } 378 } 379 /** 380 * 测试http连接是å¦å¯è¿žæŽ¥ 381 * @param url 测试的url 382 * @param responseValidator 383 * @return 连接状æ€{@link ConnectStatus} 384 * @see #testHttpConnect(URL, Predicate) 385 */ 386 public static ConnectStatus testHttpConnect(String host,int port,Predicate<String> responseValidator){ 387 try { 388 return testHttpConnect(new URL("http",host,port,""), responseValidator); 389 } catch (Exception e) { 390 return ConnectStatus.FAIL; 391 } 392 } 393 /** 394 * 测试http连接是å¦å¯è¿žæŽ¥ 395 * @param url 396 * @param responseValidator 397 * @return 连接æˆåŠŸ{@link ConnectStatus#CONNECTABLE}返回{@code true}, 398 * 连接失败{@link ConnectStatus#FAIL}返回{@code false} 399 * å“åº”æ— æ•ˆ{@link ConnectStatus#INVALID_RESPONE}抛出异常 400 * @see #testHttpConnect(URL, Predicate) 401 * @throws IllegalStateException 连接å“åº”æ— æ•ˆ 402 */ 403 public static boolean testHttpConnectChecked(URL url,Predicate<String> responseValidator){ 404 ConnectStatus status = testHttpConnect(url,responseValidator); 405 checkState(status != ConnectStatus.INVALID_RESPONE,"INVALID INVALID_RESPONE from %s",url); 406 return status == ConnectStatus.CONNECTABLE; 407 } 408 /** 409 * 测试http连接是å¦å¯è¿žæŽ¥ 410 * @param url 411 * @param responseValidator 412 * @return 413 * @see #testHttpConnectChecked(URL, Predicate) 414 * @throws IllegalStateException 连接å“åº”æ— æ•ˆ,连接状æ€ä¸º {@link ConnectStatus#INVALID_RESPONE}æ—¶ 415 */ 416 public static boolean testHttpConnectChecked(String url,Predicate<String> responseValidator){ 417 try { 418 return testHttpConnectChecked(new URL(url),responseValidator); 419 } catch (Exception e) { 420 return false; 421 } 422 } 423 /** 424 * 测试http连接是å¦å¯è¿žæŽ¥ 425 * @param host 426 * @param port 427 * @param responseValidator 428 * @return 429 * @see #testHttpConnectChecked(URL, Predicate) 430 * @throws IllegalStateException 连接å“åº”æ— æ•ˆ,连接状æ€ä¸º {@link ConnectStatus#INVALID_RESPONE}æ—¶ 431 */ 432 public static boolean testHttpConnectChecked(String host,int port,Predicate<String> responseValidator){ 433 try { 434 return testHttpConnectChecked(new URL("http",host,port,""), responseValidator); 435 } catch (Exception e) { 436 return false; 437 } 438 } 439}