Java socket - 使用代理服務器


為什么使用代理服務器不需要多說了。

使用Proxy

Java提供了Proxy類實現使用代理進行通信。

Proxy類的構造器Proxy(Proxy.Type type, SocketAddress sa)。其中type表示代理類型,代理類型有三種:DIRECT(表示不使用代理)、HTTP(表示使用高級協議代理比如http或FTP)、SOCKETS(表示使用sockets代理)。sa表示代理地址。

一旦創建Proxy對象后,程序就可以在使用URLConnection打開連接時,或者創建用socket連接時,傳入一個Proxy對象作為本次連接使用的代理服務器。

其中URL提供了一個URLConnection openConnection(Proxy proxy); Socket則提供了一個Socket(Proxy proxy)構造器。

使用URL的openConnection為例:

public static void httpProxy() throws IOException {
        // 代理對象
        Proxy proxy = new Proxy(Proxy.Type.HTTP,
                new InetSocketAddress(IP, PORT));

        // 需要訪問的地址
        String urlStr = "http://www.zhyea.com";
        // 創建連接
        URL url = new URL(urlStr);
        URLConnection conn = url.openConnection(proxy);
        // 輸出訪問結果
        try {
            Scanner scan = new Scanner(conn.getInputStream());
            StringBuilder builder = new StringBuilder();
            while (scan.hasNextLine()) {
                builder.append(scan.nextLine()).append(StringUtils.NEWLINE);
            }
            System.out.println(builder.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

使用ProxySelector

先不多做解釋,直接上代碼:

public static void httpProxy() throws IOException {

        ProxySelector.setDefault(new ProxySelector() {

            @Override
            public List<Proxy> select(URI uri) {
                List<Proxy> list = new ArrayList<Proxy>();
                list.add(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(
                        "10.10.8.84", 8080)));
                return list;
            }

            @Override
            public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
                System.out.println("連接代理失敗!");
            }

        });
        // 需要訪問的地址
        String urlStr = "http://www.baidu.com";
        // 創建連接
        URL url = new URL(urlStr);
       URLConnection conn = url.openConnection();
        // 輸出訪問結果
        try {
            Scanner scan = new Scanner(conn.getInputStream());
            StringBuilder builder = new StringBuilder();
            while (scan.hasNextLine()) {
                builder.append(scan.nextLine()).append(StringUtils.NEWLINE);
            }
            System.out.println(builder.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

如上的代碼並沒有顯式的指定代理服務器,但是在我提供一個無效的代理IP的時候,控制台輸出了“連接代理失敗”的字樣。說明程序使用了我提供的代理。

ProxySelector是一個抽象類,它提供了兩個方法select、connectFailed需要用戶自己實現:

  • select:返回代理服務器列表(據測試會默認使用第一個代理);
  • connectFailed:連接代理失敗時的處理方法。

Java為ProxySelector提供了一個實現類DefaultProxySelector,且將之注冊為默認的代理實現類,一般不需要顯式實現,需要時可以通過ProxySelector.getDefault()來調用。簡單說下DefaultProxySelector對ProxySelector的實現:

  • select:會根據系統屬性來選擇使用代理服務器。關於代理服務器的系統屬性有如下三個http.proxyHost,http.proxyPort,http.nonProxyHosts(具體使用方法參看實例);
  • connectFailed:連接代理失敗后會嘗試使用直接連接。

如下是一個實例(懶得自己寫了,直接在網上找了一個):

package com.zhyea.olproxy.test;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Properties;
import java.util.Scanner;

public class ProxySelectorTest {
    // 測試本地JVM的網絡默認配置
    public void setLocalProxy() {
        Properties prop = System.getProperties();
        // 設置HTTP訪問要使用的代理服務器的地址
        prop.setProperty("http.proxyHost", "10.10.8.84");
        // 設置HTTP訪問要使用的代理服務器的端口
        prop.setProperty("http.proxyPort", "8080");
        // 設置HTTP訪問不需要通過代理服務器訪問的主機,
        // 可以使用*通配符,多個地址用|分隔
        prop.setProperty("http.nonProxyHosts", "localhost|10.20.*");
        // 設置安全HTTP訪問使用的代理服務器地址與端口
        // 它沒有https.nonProxyHosts屬性,它按照http.nonProxyHosts 中設置的規則訪問
        prop.setProperty("https.proxyHost", "192.168.0.96");
        prop.setProperty("https.proxyPort", "443");
        // 設置FTP訪問的代理服務器的主機、端口以及不需要使用代理服務器的主機
        prop.setProperty("ftp.proxyHost", "10.10.0.96");
        prop.setProperty("ftp.proxyPort", "2121");
        prop.setProperty("ftp.nonProxyHosts", "localhost|10.10.*");
        // 設置socks代理服務器的地址與端口
        prop.setProperty("socks.ProxyHost", "10.10.0.96");
        prop.setProperty("socks.ProxyPort", "1080");
    }

    // 清除proxy設置
    public void removeLocalProxy() {
        Properties prop = System.getProperties();
        // 清除HTTP訪問的代理服務器設置
        prop.remove("http.proxyHost");
        prop.remove("http.proxyPort");
        prop.remove("http.nonProxyHosts");
        // 清除HTTPS訪問的代理服務器設置
        prop.remove("https.proxyHost");
        prop.remove("https.proxyPort");
        // 清除FTP訪問的代理服務器設置
        prop.remove("ftp.proxyHost");
        prop.remove("ftp.proxyPort");
        prop.remove("ftp.nonProxyHosts");
        // 清除SOCKS的代理服務器設置
        prop.remove("socksProxyHost");
        prop.remove("socksProxyPort");
    }

    // 測試HTTP訪問
    public void showHttpProxy() throws MalformedURLException, IOException {
        URL url = new URL("http://www.baidu.com");
        // 直接打開連接,但系統會調用剛設置的HTTP代理服務器
         URLConnection conn = url.openConnection(); //
        Scanner scan = new Scanner(conn.getInputStream());
        // 讀取遠程主機的內容
        while (scan.hasNextLine()) {
            System.out.println(scan.nextLine());
        }
    }

    public static void main(String[] args) throws IOException {
        ProxySelectorTest test = new ProxySelectorTest();
        test.setLocalProxy();
        test.showHttpProxy();
        test.removeLocalProxy();
    }
}

這個寫得很全了。

就這樣。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM