• 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();
        }
    }

    这个写得很全了。

    就这样。

  • 相关阅读:
    日期帮助类
    校验帮助类
    缓存帮助类
    数据转换帮助类
    枚举帮助类
    sql 不常用的知识点记录
    反射实例化不同类型的实例
    xml读取
    读取字段别名
    动态类型赋值处理
  • 原文地址:https://www.cnblogs.com/amunote/p/4169886.html
Copyright © 2020-2023  润新知