服务器之家

服务器之家 > 正文

Java使用代理进行网络连接方法示例

时间:2021-01-10 11:35     来源/作者:思想永无止境

需求是这样的:

一、界面上要有这样几种代理类型可以选。

1.HTTP代理

2.Socks代理

3.不使用代理(直连)

4.使用浏览器设置(浏览器也是HTTP、Socks、直连三种)。

可参考QQ登录设置里的代理能,其实跟qq的代理功能是一样的。

二、测试使用所填写的代理配置信息是否可连接

三、记录用户上次选择的代理配置,默认使用用户上次使用的代理配置进行网络连接

程序运行环境是WindowsXP、Windows7、Windows8系统。

使用的技术为Java7,Swing,CXF。

难点:

1.如何进行全居的代理设置:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/**
 * 网络代理Bean
 *
 * @author tang
 */
public class NetworkBean implements Serializable {
  private static final long serialVersionUID = 1L;
  // private static sun.misc.BASE64Encoder base64Encoder = new sun.misc.BASE64Encoder();
  private Proxy.Type type;// 代理类型
  private String address;// ip 地址
  private String port;// 端口号
  private String username;// 代理服务器用户名
  private String password;// 代理服务器用户密码
  private String domain;// 域
  private String typeText;// 代理类型显示的文本
  public NetworkBean() {
  }
  public NetworkBean(Type type, String address, String port, String username, String password) {
    this.type = type;
    this.address = address;
    this.port = port;
    this.username = username;
    this.password = password;
  }
  public NetworkBean(Type type, String address, String port, String username, String password, String domain) {
    super();
    this.type = type;
    this.address = address;
    this.port = port;
    this.username = username;
    this.password = password;
    this.domain = domain;
  }
  public Proxy.Type getType() {
    return type;
  }
  public void setType(Proxy.Type type) {
    this.type = type;
  }
  public String getAddress() {
    return address;
  }
  public void setAddress(String address) {
    this.address = address;
  }
  public String getPort() {
    return port;
  }
  public void setPort(String port) {
    this.port = port;
  }
  public String getUsername() {
    return username;
  }
  public void setUsername(String username) {
    this.username = username;
  }
  public String getPassword() {
    return password;
  }
  public void setPassword(String password) {
    this.password = password;
  }
  public String getDomain() {
    return domain;
  }
  public void setDomain(String domain) {
    this.domain = domain;
  }
  public String getTypeText() {
    return typeText;
  }
  public void setTypeText(String typeText) {
    this.typeText = typeText;
  }
  /**
   * return domain + "\" + username
   */
  public String getDomainAndUsername() {
    return (Utils.toString(domain).trim().isEmpty()) ? username : domain.trim() + "\\" + username;
  }
  /**
   * return domain + "\" + username + ":" + password
   */
  public String getDomainAndUsernameAndPassword() {
    return getDomainAndUsername() + ":" + password;
  }
  /**
   * return username + ":" + password
   */
  public String getUsernameAndPassword() {
    return username + ":" + password;
  }
  /**
   * return (domain + "\" + username + ":" + password) to 64 bit
   */
  public String getDomainAndUsernameAndPassword64() {
    return org.apache.commons.codec.binary.Base64.encodeBase64String(getDomainAndUsernameAndPassword().getBytes());
  }
  @Override
  public String toString() {
    return "NetworkBean [type=" + type + ", typeText=" + typeText + ", address=" + address + ", port=" + port + ", username=" + username + ", password="
        + password + ", domain=" + domain + "]";
  }
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
   * 根据指定的代理信息设置系统全局的网络代理
   *
   * @param networkBean
   */
  public static void setNetworkProxyBySystem(NetworkBean networkBean) {
    System.out.println("System Set Proxy : " + networkBean);
    if (isUserProxy(networkBean)) {
      if (networkBean.getType() == Proxy.Type.SOCKS) {
        System.getProperties().remove("http.proxyHost");
        System.getProperties().remove("http.proxyPort");
        System.getProperties().setProperty("socksProxyHost", networkBean.getAddress());
        System.getProperties().setProperty("socksProxyPort", networkBean.getPort());
      } else {
        System.getProperties().setProperty("http.proxyHost", networkBean.getAddress());
        System.getProperties().setProperty("http.proxyPort", networkBean.getPort());
      }
      Authenticator.setDefault(new BairuiAuthenticator(networkBean.getDomainAndUsername(), networkBean.getPassword()));
    } else if (networkBean != null) {
      System.getProperties().remove("proxySet");
      System.getProperties().remove("socksProxySet");
      System.getProperties().remove("http.proxyHost");
      System.getProperties().remove("http.proxyPort");
      System.getProperties().remove("socksProxyHost");
      System.getProperties().remove("socksProxyPort");
    }
  }
  /**
   * 网络用户名密码校验提供者
   */
  public static class BairuiAuthenticator extends Authenticator {
    private String username, password;
    public BairuiAuthenticator(String username, String password) {
      this.username = username;
      this.password = password;
    }
    protected PasswordAuthentication getPasswordAuthentication() {
      return new PasswordAuthentication(username, password == null ? null : password.toCharArray());
    }
  }

2.如何让CXF的Service使用系统的代理:

?
1
2
3
4
5
6
7
8
9
10
11
/**
  * 为WebService接口添加网络代理支持:httpClientPolicy.setAllowChunking(false);
  *
  * @param client
  */
 public static void setWebServiceSupportProxy(Client client) {
   HTTPConduit conduit = (HTTPConduit) client.getConduit();
   HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
   httpClientPolicy.setAllowChunking(false);
   conduit.setClient(httpClientPolicy);
 }

3.使用浏览器设置:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
   * 读取用户注册表获取浏览器的代理设置
   *
   * @return 该方法不会返回null值也不会抛出异常
   */
  public static NetworkBean getBrowserProxy() {
    NetworkBean networkBean = new NetworkBean();
    networkBean.setTypeText(typeTexts[3]);
    networkBean.setType(Proxy.Type.DIRECT);
    String key = "reg query \"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\"";// 注册表浏览器代理key
    try {
      Process exec = Runtime.getRuntime().exec(key);
      try (InputStreamReader i = new InputStreamReader(exec.getInputStream()); BufferedReader ir = new BufferedReader(i)) {
        for (String line = ir.readLine(); line != null; line = ir.readLine()) {
          if (line.indexOf("ProxyServer") >= 0) {
            String[] split1 = line.split("  ");
            if (split1.length > 3) {
              String[] split2 = split1[3].trim().split(":");
              if (split2.length > 1) {
                if (!Utils.toString(split2[0]).isEmpty() && !Utils.toString(split2[1]).isEmpty()) {
                  networkBean.setAddress(split2[0]);
                  networkBean.setPort(split2[1]);
                  networkBean.setType(Proxy.Type.HTTP);
                  break;
                }
              }
            }
          }
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    } catch (Exception e) {// 从注册表读取失败
      e.printStackTrace();
    }
    return networkBean;
  }

4.测试代理是否可用

因为程序中使用了服务器的两个不同的端口,所以需要测试两个端口是否都可连。

如果使用了多台服务器,更加需要分别测试了。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/**
  * 测试网络代理是否能通过连接,如果不通过抛出异常
  *
  * @throws Exception
  */
 private static void testNetworkProxy() throws Exception {
   testWebService();
   testURLConnection();
 }
 /**
  * 测试CXF Service接口50367端口
  *
  * @param networkBean
  * @throws Exception
  */
 public static void testWebService() throws Exception {
   JcptLoginService service = WebServiceUtils.getService(JcptLoginService.class, GeneralWebServiceAddress.LOGIN_SERVICE_URL_ADD);
   String result = service.getLoginPicture();
   System.out.println(result);
 }
 /**
  * 从HttpURLConnection对象读取指定字符,如果不匹配则抛出异常
  *
  * @param connection
  * @throws Exception
  */
 private static void checkConnectionContent(HttpURLConnection connection) throws Exception {
   try (InputStream inputStream = connection.getInputStream()) {
     byte[] b = new byte[1024];
     boolean success = false;
     StringBuffer sb = new StringBuffer();
     for (int i = inputStream.read(b); i > 0; i = inputStream.read(b)) {
       String tempStr = new String(b, 0, i);
       sb.append(tempStr);
       if (tempStr.indexOf("3,file not found") >= 0) {// service固定返回这个字符串,如果service作了更改此处也应更改
         success = true;
         break;
       }
     }
     if (!success) {
       String str = sb.toString();
       if (str.length() > 3) {
         char char0 = str.charAt(0);
         char char1 = str.charAt(1);
         if (Utils.isNumber(char0 + "") && char1 == ',') {
           success = true;
         }
       }
     }
     if (!success) {
       throw new RuntimeException("result content does not meet expectations.");
     }
   } catch (Exception ex) {
     throw ex;
   }
 }
 /**
  * 测试文件下载接口9067端口
  *
  * @param networkBean
  * @throws Exception
  */
 public static void testURLConnection() throws Exception {
   HttpURLConnection connection = (HttpURLConnection) new URL(GeneralWebServiceAddress.FILE_DOWN_URL_ADD + "path=").openConnection();
   checkConnectionContent(connection);
 }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
/**
  * 测试代理服务器连接
  */
 private void testProxyConnection() {
   NetworkBean readNetworkBean = NetworkProxyTool.readNetworkBean();// 先获得正在使用的NetworkBean
   try {
     NetworkBean networkBean = createNetworkBean();// 根据用户填写的信息创建的NetworkBean对象
     showTestResultDialog(NetworkProxyTool.testNetworkProxyBySystem(networkBean));
   } catch (Exception ex) {
     showTestResultDialog(false);
   }
   NetworkProxyTool.setNetworkProxyBySystem(readNetworkBean);// 测试结束,还原原来的NetworkBean
 }

5.因为java连接网络时,如果使用当前的代理连接失败,那么就会使用操作系统中缓存的代理进行网络连接,如何是测试连接时不使用操作系统缓存,但测试结束后使用操作系统缓存。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
  * 设置长连接和验证信息缓存是否开启
  *
  * @param keepAlive
  */
 public static void setKeepAliveAndAuthCache(boolean keepAlive) {
   System.setProperty("http.keepAlive", keepAlive + "");// 设置是否开始长连接,如果为false可以防止连接被缓存(如果连接被缓存,用户名密码等所有信息都会被缓存)
   if (keepAlive) {
     AuthCacheValue.setAuthCache(new AuthCacheImpl());
   } else {
     // 设置一个空的实现AuthCache可以防止用户名密码信息被缓存
     AuthCacheValue.setAuthCache(new AuthCache() {
       public void remove(String pkey, AuthCacheValue entry) {
       }
       public void put(String pkey, AuthCacheValue value) {
       }
       public AuthCacheValue get(String pkey, String skey) {
         return null;
       }
     });
   }
 }

在登录之前:

?
1
2
NetworkProxyTool.setKeepAliveAndAuthCache(false);
new.Login();

登录成功后:

?
1
NetworkProxyTool.setKeepAliveAndAuthCache(true);

6.保存用户的代理配置:

因为直接序列化自定义类型的对象,会存在版本问题(比如这个类的包名、类名改了,就死定了)。
所以不能直接序列化自定义类的对象,二是将自定义类对象的属性转成字典(Map),然后序列化map。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
   * 读取本地网络代理设置配置文件
   *
   * @return
   */
  public static NetworkBean readNetworkBean() {
    NetworkBean networkBean = getCurrNetworkBean(readNetworkBeanMap());
    if (networkBean == null) {
      networkBean = new NetworkBean();
      networkBean.setType(Proxy.Type.DIRECT);
    }
    return networkBean;
  }
  /**
   * 获取用户上次选择网络代理设置
   *
   * @param map
   * @return
   */
  public static NetworkBean getCurrNetworkBean(Map<String, Object> map) {
    putBrowserProxy(map);
    return (NetworkBean) map.get(getTypeMapKey(map));
  }
  /**
   * 将浏览器的信息存放入代理信息总配置map
   *
   * @param map
   */
  private static void putBrowserProxy(Map<String, Object> map) {
    if (browserProxyBean == null) {
      browserProxyBean = getBrowserProxy();
    }
    NetworkBean networkBeanBrowser = (NetworkBean) map.get(key_browser);
    if (networkBeanBrowser == null) {
      networkBeanBrowser = browserProxyBean;
    }
    if ((Utils.toString(browserProxyBean.getAddress()).isEmpty() || !browserProxyBean.getAddress().equals(networkBeanBrowser.getAddress()))
        || (Utils.toString(browserProxyBean.getPort()).isEmpty() || !browserProxyBean.getPort().equals(networkBeanBrowser.getPort()))) {
      networkBeanBrowser.setUsername(null);
      networkBeanBrowser.setPassword(null);
      networkBeanBrowser.setDomain(null);
    }
    networkBeanBrowser.setType(browserProxyBean.getType());
    networkBeanBrowser.setTypeText(browserProxyBean.getTypeText());
    networkBeanBrowser.setAddress(browserProxyBean.getAddress());
    networkBeanBrowser.setPort(browserProxyBean.getPort());
    map.put(key_browser, networkBeanBrowser);
  }

在登录之前:

?
1
2
3
4
NetworkBean networkBean = NetworkProxyTool.readNetworkBean();
NetworkProxyTool.setNetworkProxyBySystem(networkBean);
NetworkProxyTool.setKeepAliveAndAuthCache(false);
new.Login();

在用户配置完代理点击确定时:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
  * 点击确定
  */
 private void confirm() {
 
   if ((isHttp() || isSocks()) && !checkIpAndPortNotNull()) {
     return;
   }
   NetworkBean networkBean = createNetworkBean();
   if (isHttp()) {// HTTP代理
     if (networkBean.getDomain() != null) {
       networkBean.setDomain(networkBean.getDomain().trim());
     }
     proxySettingMap.put(key_http, networkBean);
     proxySettingMap.put(key_proxy_type, key_http);
   } else if (isSocks()) {// SOCKS代理
     proxySettingMap.put(key_socks, networkBean);
     proxySettingMap.put(key_proxy_type, key_socks);
   } else if (isBrowser()) {
     proxySettingMap.put(key_browser, networkBean);
     proxySettingMap.put(key_proxy_type, key_browser);
   } else {
     proxySettingMap.put(key_direct, networkBean);
     proxySettingMap.put(key_proxy_type, key_direct);
   }
   userCurrShowNetworkBean = networkBean;
   isConfirm = true;
   setVisible(false);
   NetworkProxyTool.saveNetworkProxyConfig(proxySettingMap);
 }

System Properties

Java System Properties网络设置有哪些key

http://docs.oracle.com/javase/7/docs/technotes/guides/net/properties.html

http://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html

Java System Properties优先级说明

host和port比set优先级高,也就是说set可以不用去设置。

如存在http.proxyHost和http.proxyPort时,proxySet设为false无效,系统仍然可以使用http代理。

存在socksProxyHost和socksProxyPort时,socksProxySet设为false无效,系统仍然可以使用socks代理。

http比socks优先级高,即存在http.proxyHost和http.proxyPort时,socksProxySet、socksProxyHost、socksProxyPort都会失效,系统会使用http代理。

使用java.net.Proxy

如果只是单个的连接需要使用代理,那么可以采用Proxy类进行代理连接。

说明:

1.Socket只能使用socks代理不能使用http代理。

2.Socket使用使用Authenticator来进行验证。

3.URLConnection 使用RequestProperty是只对当前连接有效,不会缓存,Authenticator是全局性的,对所有网络请求都有效,会缓存,但RequestProperty的优先级比Authenticator高。

4.只有RequestProperty需要64位编码,Authenticator不需要。

5.需要清除验证缓存的,不使用验证缓存上面已经有代码了,这里就不重复写了。

6.其实,建议采用全局性的代理连接,不管是URLConnection 还是Socket 都简单方便、统一。

代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
NetworkBean httpBean = new NetworkBean(Proxy.Type.HTTP, "192.168.77.5", "8888", "tzc", "123", null);
Proxy httpProxy = new Proxy(httpBean.getType(), new InetSocketAddress(httpBean.getAddress(), Integer.parseInt(httpBean.getPort())));
NetworkBean socksBean = new NetworkBean(Proxy.Type.SOCKS, "192.168.77.5", "9999", "tzc", "123", "ttt");
Proxy socksProxy = new Proxy(socksBean.getType(), new InetSocketAddress(socksBean.getAddress(), Integer.parseInt(socksBean.getPort())));
URLConnection httpProxyConnection = new URL("http://www.baidu.com/").openConnection(httpProxy);
//或者Authenticator.setDefault(new BairuiAuthenticator(networkBean.getDomainAndUsername(), networkBean.getPassword()));
httpProxyConnection.setRequestProperty("Proxy-Authorization", "Basic "+httpBean.getDomainAndUsernameAndPassword64());
URLConnection socksProxyConnection = new URL("http://www.baidu.com/").openConnection(socksProxy);
//或者Authenticator.setDefault(new BairuiAuthenticator(networkBean.getDomainAndUsername(), networkBean.getPassword()));
socksProxyConnection.setRequestProperty("Proxy-Authorization", "Basic "+httpBean.getDomainAndUsernameAndPassword64());
Socket socket = new Socket(socksProxy);
Authenticator.setDefault(new BairuiAuthenticator(networkBean.getDomainAndUsername(), networkBean.getPassword()));
socket.connect(new InetSocketAddress("www.baidu.com", 5555));

总结

以上就是本文关于Java使用代理进行网络连接方法示例的全部内容,希望对大家学习Java有所帮助,欢迎各位浏览本站其他专题并随时留言,小编会及时回复大家的。

原文链接:http://blog.csdn.net/u012643122/article/details/53032482

标签:

相关文章

热门资讯

2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全
2020微信伤感网名听哭了 让对方看到心疼的伤感网名大全 2019-12-26
Intellij idea2020永久破解,亲测可用!!!
Intellij idea2020永久破解,亲测可用!!! 2020-07-29
背刺什么意思 网络词语背刺是什么梗
背刺什么意思 网络词语背刺是什么梗 2020-05-22
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享
歪歪漫画vip账号共享2020_yy漫画免费账号密码共享 2020-04-07
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总
苹果12mini价格表官网报价 iPhone12mini全版本价格汇总 2020-11-13
返回顶部