首页 > 编程笔记 > Java笔记 阅读:7

Java Proxy代理服务器编程(附带实例)

代理服务器(Proxy Server)的功能是代理网络用户去取得网络信息。形象地说,它是网络信息的中转站,是个人网络和 Internet 服务商之间的中间代理机构,负责转发合法的网络信息,并对转发进行控制和登记。

随着 Internet 与 Intranet 的飞速发展,作为连接 Internet 与 Intranet 的桥梁,代理服务器在实际应用中发挥着极其重要的作用。

Java Proxy创建网络连接

Java 在 java.net 包下提供了 Proxy 和 ProxySelector 两个类。

Proxy 代表一个代理服务器,可以在打开 URLConnection 连接时指定 Proxy,创建 Socket 连接时也可以指定 Proxy。

ProxySelector 代表一个代理选择器,它提供了对代理服务器更加灵活地控制,可以对 HTTP、HTTPS、FTP、SOCKS 等进行分别设置,而且还可以设置不需要通过代理服务器的主机和地址。通过使用 ProxySelector,可以实现与在 Internet Explorer、Firefox 等软件中设置代理服务器类似的效果。

浏览器中代理服务器的设置页面如下图所示:


图 1 Internet Explorer设置代理服务器

Proxy 有一个构造器,用于创建表示代理服务器的 Proxy 对象:
Proxy(Proxy.Type type, SocketAddress socketAddress)

一旦创建了 Proxy 对象之后,程序就可以在使用 URLConnection 打开连接时,或者创建 Socket 连接时传入一个 Proxy 对象,作为本次连接所使用的代理服务器。

其中,URL 类包含了一个 URLConnection openConnection(Proxy proxy) 方法,该方法使用指定的代理服务器来打开连接;而 Socket 类则提供了一个 Socket(Proxy proxy) 构造器,该构造器使用指定的代理服务器创建一个没有连接的 Socket 对象。

接下来,以 URLConnection 为例来介绍如何在 URLConnection 中使用代理服务器。
import java.io.IOException;
import java.net.*;
import java.util.Scanner;

public class Demo {
    public static void main(String[] args) throws IOException {
        // 代理服务器的IP地址和端口
        String ip = "118.190.158.17";
        int port = 8080;
        // 定义需要访问的网站地址
        String urlStr = "http://abc.com";
        URL url = new URL(urlStr);
        // 创建一个代理服务器对象
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ip, port));
        // 使用指定的代理服务器打开连接
       URLConnection conn = url.openConnection(proxy);
        // 设置超时时长
        conn.setConnectTimeout(3000);
        // 通过代理服务器读取数据的Scanner
        Scanner scan = new Scanner(conn.getInputStream());
        System.out.println("==================返回服务器响应的内容==================");
        while (scan.hasNextLine()) {
            String line = scan.nextLine();
            // 在控制台输出网页资源内容
            System.out.println(line);
        }
    }
}
程序的运行结果如下:
============返回服务器响应的内容=============
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Apache Tomcat/8.5.65</title>
    <link href="favicon.ico" rel="icon" type="image/x-icon" />
    <link href="tomcat.css" rel="stylesheet" type="text/css" />
  </head>
程序中,第 16 行代码创建了一个 Proxy 对象,第 19 行代码就是用 Proxy 对象来打开 URLConnection 连接。接下来程序使用 URLConnection 读取了一份网络资源,此时的 URLConnection 并不是直接连接到 http://abc.com,而是通过代理服务器去访问该网站。

Java ProxySelector自动选择代理服务器

直接使用 Proxy 对象可以在打开 URLConnection 或 Socket 时指定代理服务器,但使用这种方式每次打开连接时都需要显式地设置代理服务器,比较麻烦。如果希望每次打开连接时总是具有默认的代理服务器,则可以借助于 ProxySelector 类来实现。

ProxySelector 类代表一个代理选择器,它本身是一个抽象类,程序无法创建它的实例,开发者可以考虑继承 ProxySelector 类来实现自己的代理选择器。

实现 ProxySelector 类的步骤非常简单,程序只要定义一个继承 ProxySelector 类的类,并让该类实现如下两个抽象方法:
实现了自己的 ProxySelector 类之后,调用 ProxySelector 类的 setDefault(ProxySelector ps) 静态方法来注册该代理选择器即可。

接下来,通过案例来演示如何让自定义的 ProxySelector 类来自动选择代理服务器。
import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Demo {
    public static void main(String[] args) throws IOException {
        // 设置默认代理选择器
        ProxySelector.setDefault(new ProxySelector() {
            @Override
            public List<Proxy> select(URI uri) {
                List<Proxy> proxyList = new ArrayList<Proxy>();
                // 代理服务器的IP地址和端口
                String ip1 = "118.190.158.17";
                int port1 = 8080;
                // 创建一个代理服务器对象
                Proxy proxy1 = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ip1, port1));
                // 代理服务器的IP地址和端口
                String ip2 = "118.190.158.17";
                int port2 = 9090;
                // 创建一个代理服务器对象
                Proxy proxy2 = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ip2, port2));
                proxyList.add(proxy2);
                proxyList.add(proxy1);
                return proxyList;
            }

            @Override
            public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
                System.out.println("连接代理服务器失败!");
            }
        });

        // 定义需要访问的网站地址
        String urlStr = "http://aaajy.net";
        URL url = new URL(urlStr);
        // 不使用指定的代理服务器打开连接
        URLConnection conn = url.openConnection();
        // 设置超时时长
        conn.setConnectTimeout(3000);
        // 通过代理服务器读取数据的Scanner
        Scanner scan = new Scanner(conn.getInputStream());
        System.out.println("==================返回服务器响应的内容==================");
        while (scan.hasNextLine()) {
            String line = scan.nextLine();
            // 在控制台输出网页资源内容
            System.out.println(line);
        }
    }
}
程序的运行结果如下:
连接代理服务器失败!
============返回服务器响应的内容=============
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Apache Tomcat/8.5.65</title>
    <link href="favicon.ico" rel="icon" type="image/x-icon" />
    <link href="tomcat.css" rel="stylesheet" type="text/css" />
  </head>
程序中,虽然没有使用代理服务器打开连接,但是代理服务器仍然起作用了,也就是说程序默认总会使用注册的代理服务器。

注意,代理服务器列表中保存的某个服务器无法连接的时候会出现“连接代理服务器失败!”的错误。

相关文章