Java动态替换InetAddress中DNS的做法简单分析2
Posted zolo®
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java动态替换InetAddress中DNS的做法简单分析2相关的知识,希望对你有一定的参考价值。
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- import java.net.HttpURLConnection;
- import java.net.InetAddress;
- import java.net.MalformedURLException;
- import java.net.URL;
- import java.net.UnknownHostException;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import sun.net.spi.nameservice.NameService;
- public class JavaDNSCacheTest {
- /**
- * 经测试,二种方式在Windows环境都可以, Linux环境待测
- *
- * @param args
- * @throws Exception
- */
- public static void main(String[] args) throws Exception {
- /* 1. 动态替换AddressCache */
- // changeDNSWithAddressCache();
- /* 1. 动态代理NameService */
- changeDNSWithNameService();
- }
- public static void changeDNSWithNameService() throws Exception {
- /* 1. 获取反身类 */
- Class<?> addressClass = InetAddress.class;
- /* 2. 获取addressCache字段 */
- try {
- Field nameServiceField = addressClass.getDeclaredField("nameService");// 对于Jrockit或IBM JDK
- nameServiceField.setAccessible(true);
- sun.net.spi.nameservice.NameService nameService = (NameService) nameServiceField.get(null);
- nameServiceField.set(null, new NameServiceProxy(nameService));
- nameServiceField.setAccessible(false);
- } catch (NoSuchFieldException e) {
- Field nameServicesField = addressClass.getDeclaredField("nameServices");// 对于OpenJDK
- nameServicesField.setAccessible(true);
- List<sun.net.spi.nameservice.NameService> nameServices = (List<sun.net.spi.nameservice.NameService>) nameServicesField.get(null);
- if (nameServices != null && nameServices.size() > 0) {
- /* 置换为代理实例 */
- nameServices.set(0, new NameServiceProxy(nameServices.get(0)));
- } else {
- // 可能为空吗? 待测
- }
- nameServicesField.setAccessible(false);
- }
- getHttpConent("www.baidu.com");
- }
- public static void changeDNSWithCddressCache() throws Exception {
- /* 1. 获取反身类 */
- Class<?> addressClass = InetAddress.class;
- /* 2. 获取addressCache字段 */
- Field addressCacheField = addressClass.getDeclaredField("addressCache");
- /* 3. 获取addressCache */
- addressCacheField.setAccessible(true);
- Object addressCache = addressCacheField.get(null);
- addressCacheField.setAccessible(false);
- /* 4. 获取addressCache的反射类 */
- Class<?> addressCacheClass = addressCache.getClass();
- /* 5. 获取addressCache的put方法 */
- Method putMethod = addressCacheClass.getDeclaredMethod("put", String.class, InetAddress[].class);
- /* 5. 修改addressCache将wwww.baidu.com换成指定任意IP */
- putMethod.setAccessible(true);
- putMethod.invoke(addressCache, "www.baidu.com", new InetAddress[] { InetAddress.getByAddress(new byte[] { 115, (byte) 239, (byte) 210, 26 }) });
- putMethod.setAccessible(false);
- /* 6.测试,看看是否连通 */
- getHttpConent("www.baidu.com");
- }
- private static void getHttpConent(String host) throws MalformedURLException, IOException {
- HttpURLConnection conn = (HttpURLConnection) new URL("http://" + host).openConnection();
- try {
- conn.setConnectTimeout(3000);// 减少连接时间,方便测试
- conn.setDefaultUseCaches(false);
- conn.setDoInput(true);
- conn.setRequestMethod("GET");
- conn.connect();
- int code = conn.getResponseCode();
- System.out.format("REST[%d]\n", code);
- InputStream in = null;
- in = conn.getErrorStream();// 如果非2xx,则由errorStream获取输出.
- if (in == null) {
- in = conn.getInputStream();
- }
- if (in != null) {
- BufferedReader reader = new BufferedReader(new InputStreamReader(in));
- for (String line = null; (line = reader.readLine()) != null;) {
- System.out.println(line);
- }
- }
- } finally {
- if (conn != null) {
- conn.disconnect();
- }
- }
- }
- @SuppressWarnings("restriction")
- public static class NameServiceProxy implements sun.net.spi.nameservice.NameService {
- final sun.net.spi.nameservice.NameService nameService;
- final Map<String, InetAddress[]> mapping = new HashMap<String, InetAddress[]>();
- {
- try {
- mapping.put("www.baidu.com", new InetAddress[] { InetAddress.getByAddress(new byte[] { 115, (byte) 239, (byte) 210, 26 }) });
- } catch (UnknownHostException e) {
- e.printStackTrace();
- }
- }// 实例初始化表
- public NameServiceProxy(sun.net.spi.nameservice.NameService nameService) {
- this.nameService = nameService;
- }
- @Override
- public String getHostByAddr(byte[] addr) throws UnknownHostException {
- return this.nameService.getHostByAddr(addr);
- }
- @Override
- public InetAddress[] lookupAllHostAddr(String host) throws UnknownHostException {
- if (mapping.containsKey(host)) {
- return mapping.get(host);
- } else {
- return this.nameService.lookupAllHostAddr(host);
- }
- }
- }
- }
以上是关于Java动态替换InetAddress中DNS的做法简单分析2的主要内容,如果未能解决你的问题,请参考以下文章
将字符串转换为 InetAddress 而不进行 DNS 查找
--------------------------------------网络编程(UDP)
在java中,InetAddress.getLocalHost() 和 InetAddress.getByName("127.0.0.1") 有啥区别