Java动态替换InetAddress中DNS的做法简单分析2

Posted zolo®

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java动态替换InetAddress中DNS的做法简单分析2相关的知识,希望对你有一定的参考价值。

  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStream;
  4. import java.io.InputStreamReader;
  5. import java.lang.reflect.Field;
  6. import java.lang.reflect.Method;
  7. import java.net.HttpURLConnection;
  8. import java.net.InetAddress;
  9. import java.net.MalformedURLException;
  10. import java.net.URL;
  11. import java.net.UnknownHostException;
  12. import java.util.HashMap;
  13. import java.util.List;
  14. import java.util.Map;
  15. import sun.net.spi.nameservice.NameService;
  16. public class JavaDNSCacheTest {
  17.         /**
  18.          * 经测试,二种方式在Windows环境都可以, Linux环境待测
  19.          *
  20.          * @param args
  21.          * @throws Exception
  22.          */
  23.         public static void main(String[] args) throws Exception {
  24.                 /* 1. 动态替换AddressCache */
  25.                 // changeDNSWithAddressCache();
  26.                 /* 1. 动态代理NameService */
  27.                 changeDNSWithNameService();
  28.         }
  29.         public static void changeDNSWithNameService() throws Exception {
  30.                 /* 1. 获取反身类 */
  31.                 Class<?> addressClass = InetAddress.class;
  32.                 /* 2. 获取addressCache字段 */
  33.                 try {
  34.                         Field nameServiceField = addressClass.getDeclaredField("nameService");// 对于Jrockit或IBM JDK
  35.                         nameServiceField.setAccessible(true);
  36.                         sun.net.spi.nameservice.NameService nameService = (NameService) nameServiceField.get(null);
  37.                         nameServiceField.set(null, new NameServiceProxy(nameService));
  38.                         nameServiceField.setAccessible(false);
  39.                 } catch (NoSuchFieldException e) {
  40.                         Field nameServicesField = addressClass.getDeclaredField("nameServices");// 对于OpenJDK
  41.                         nameServicesField.setAccessible(true);
  42.                         List<sun.net.spi.nameservice.NameService> nameServices = (List<sun.net.spi.nameservice.NameService>) nameServicesField.get(null);
  43.                         if (nameServices != null && nameServices.size() > 0) {
  44.                                 /* 置换为代理实例 */
  45.                                 nameServices.set(0, new NameServiceProxy(nameServices.get(0)));
  46.                         } else {
  47.                                 // 可能为空吗? 待测
  48.                         }
  49.                         nameServicesField.setAccessible(false);
  50.                 }
  51.                 getHttpConent("www.baidu.com");
  52.         }
  53.         public static void changeDNSWithCddressCache() throws Exception {
  54.                 /* 1. 获取反身类 */
  55.                 Class<?> addressClass = InetAddress.class;
  56.                 /* 2. 获取addressCache字段 */
  57.                 Field addressCacheField = addressClass.getDeclaredField("addressCache");
  58.                 /* 3. 获取addressCache */
  59.                 addressCacheField.setAccessible(true);
  60.                 Object addressCache = addressCacheField.get(null);
  61.                 addressCacheField.setAccessible(false);
  62.                 /* 4. 获取addressCache的反射类 */
  63.                 Class<?> addressCacheClass = addressCache.getClass();
  64.                 /* 5. 获取addressCache的put方法 */
  65.                 Method putMethod = addressCacheClass.getDeclaredMethod("put", String.class, InetAddress[].class);
  66.                 /* 5. 修改addressCache将wwww.baidu.com换成指定任意IP */
  67.                 putMethod.setAccessible(true);
  68.                 putMethod.invoke(addressCache, "www.baidu.com", new InetAddress[] { InetAddress.getByAddress(new byte[] { 115, (byte) 239, (byte) 210, 26 }) });
  69.                 putMethod.setAccessible(false);
  70.                 /* 6.测试,看看是否连通 */
  71.                 getHttpConent("www.baidu.com");
  72.         }
  73.         private static void getHttpConent(String host) throws MalformedURLException, IOException {
  74.                 HttpURLConnection conn = (HttpURLConnection) new URL("http://" + host).openConnection();
  75.                 try {
  76.                         conn.setConnectTimeout(3000);// 减少连接时间,方便测试
  77.                         conn.setDefaultUseCaches(false);
  78.                         conn.setDoInput(true);
  79.                         conn.setRequestMethod("GET");
  80.                         conn.connect();
  81.                         int code = conn.getResponseCode();
  82.                         System.out.format("REST[%d]\n", code);
  83.                         InputStream in = null;
  84.                         in = conn.getErrorStream();// 如果非2xx,则由errorStream获取输出.
  85.                         if (in == null) {
  86.                                 in = conn.getInputStream();
  87.                         }
  88.                         if (in != null) {
  89.                                 BufferedReader reader = new BufferedReader(new InputStreamReader(in));
  90.                                 for (String line = null; (line = reader.readLine()) != null;) {
  91.                                         System.out.println(line);
  92.                                 }
  93.                         }
  94.                 } finally {
  95.                         if (conn != null) {
  96.                                 conn.disconnect();
  97.                         }
  98.                 }
  99.         }
  100.         @SuppressWarnings("restriction")
  101.         public static class NameServiceProxy implements sun.net.spi.nameservice.NameService {
  102.                 final sun.net.spi.nameservice.NameService nameService;
  103.                 final Map<String, InetAddress[]> mapping = new HashMap<String, InetAddress[]>();
  104.                 {
  105.                         try {
  106.                                 mapping.put("www.baidu.com", new InetAddress[] { InetAddress.getByAddress(new byte[] { 115, (byte) 239, (byte) 210, 26 }) });
  107.                         } catch (UnknownHostException e) {
  108.                                 e.printStackTrace();
  109.                         }
  110.                 }// 实例初始化表
  111.                 public NameServiceProxy(sun.net.spi.nameservice.NameService nameService) {
  112.                         this.nameService = nameService;
  113.                 }
  114.                 @Override
  115.                 public String getHostByAddr(byte[] addr) throws UnknownHostException {
  116.                         return this.nameService.getHostByAddr(addr);
  117.                 }
  118.                 @Override
  119.                 public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
  120.                         if (mapping.containsKey(host)) {
  121.                                 return mapping.get(host);
  122.                         } else {
  123.                                 return this.nameService.lookupAllHostAddr(host);
  124.                         }
  125.                 }
  126.         }
  127. }

以上是关于Java动态替换InetAddress中DNS的做法简单分析2的主要内容,如果未能解决你的问题,请参考以下文章

将字符串转换为 InetAddress 而不进行 DNS 查找

--------------------------------------网络编程(UDP)

Java将udp数据包发送到dns服务器

在java中,InetAddress.getLocalHost() 和 InetAddress.getByName("127.0.0.1") 有啥区别

java中,InetAddress为啥不能new对象

Socket编程Java中网络相关API的应用