zoukankan      html  css  js  c++  java
  • 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();
        }
    }

    这个写得很全了。

    就这样。

  • 相关阅读:
    Android Gradle Plugin指南(五)——Build Variants(构建变种版本号)
    文件内容操作篇clearerr fclose fdopen feof fflush fgetc fgets fileno fopen fputc fputs fread freopen fseek ftell fwrite getc getchar gets
    文件操作篇 close creat dup dup2 fcntl flock fsync lseek mkstemp open read sync write
    嵌入式linux应用程序调试方法
    version control system:git/hg/subversion/cvs/clearcase/vss。software configruation management。代码集成CI:Cruisecontrol/hudson/buildbot
    最值得你所关注的10个C语言开源项目
    如何记录linux终端下的操作日志
    CentOS 5.5 虚拟机安装 VirtualBox 客户端增强功能
    sizeof, strlen区别
    C/C++嵌入式开发面试题
  • 原文地址:https://www.cnblogs.com/amunote/p/4169886.html
Copyright © 2011-2022 走看看