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

这个写得很全了。

就这样。

时间: 2024-10-09 23:10:08

Java socket - 使用代理服务器的相关文章

java socket编程实例代码讲解

1.所谓socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄.应用程序通常通过"套接字"向网络发出请求或者应答网络请求. 操作java socket时用到的最多的三个方法为: accept():主要用于服务器端产生"阻塞",等待客户端的链接请求,并且返回一个客户端的Socket实例: getInputStream():方法主要用来获得网络连接输入,同时返回一个InputStream对象实例: getOutputStream

java socket通信-传输文件图片--传输图片

ClientTcpSend.java   客户端发送类 package com.yjf.test; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.net.InetSocketAddress; import java.net.Socket; public class ClientTcpSend { public static String clien

java socket 的参数选项解读(转)

java socket中有很多参数可以选择,这篇博客的目的是沉淀出这些参数的语义和用法,供自己以后查阅. 1.java socket参数选项总览 在JDK1.6中有如下参数选项: 1 public final static int TCP_NODELAY = 0x0001; 2 3 public final static int SO_BINDADDR = 0x000F; 4 5 public final static int SO_REUSEADDR = 0x04; 6 7 public fi

Java Socket编程

对于Java Socket编程而言,有两个概念,一个是ServerSocket,一个是Socket.服务端和客户端之间通过Socket建立连接,之后它们就可以进行通信了.首先ServerSocket将在服务端监听某个端口,当发现客户端有Socket来试图连接它时,它会accept该Socket的连接请求,同时在服务端建立一个对应的Socket与之进行通信.这样就有两个Socket了,客户端和服务端各一个. 客户端写服务端读 服务端代码 public class Server { public s

交通银行 Java Socket 服务启动 管理 WINDOWS 版

按照交通银行提供的无界面启动方法试验了很多次,都没有成功,所以自己动手用C# 知识写了一个. 小工具可以判断 交通银行 JAVA SOCKET 服务是否启动,并可以启动/关闭服务 主要代码如下: 判断服务是否启动 引用 :using System.Management; SelectQuery selectQuery = new SelectQuery(“select * from Win32_Process where Name = ‘java.exe’”); object cmdLine =

java socket服务器端搭建

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.ServerSocket; import java.net.Socket; import java.net.URL; public class ServerBase extends Thread { public

Java Socket编程readLine返回null,read返回-1的条件

客户端正常关闭socket的时候,服务器端的readLine()方法会返回null,或者read()方法会返回-1 Java Socket编程readLine返回null,read返回-1的条件,布布扣,bubuko.com

JAVA通信系列一:Java Socket技术总结

本文是学习java Socket整理的资料,供参考. 1       Socket通信原理 1.1     ISO七层模型 1.2     TCP/IP五层模型 应用层相当于OSI中的会话层,表示层,应用层. 区别参考:http://blog.chinaunix.net/uid-22166872-id-3716751.html 1.3     TCP报文 (1)序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记. (2)确认序号:Ack序号,占32

java socket 基于UDP/IP 协议

Java  socket 基于UDP/IP协议应用 服务器端:  1.创建DatagramSocket,指定端口号 2.创建DatagramPacket 3.接收客户端发送的数据 4.读取数据 客户端: 1.  定义发送信息: 服务器的IP 端口号  发送的内容 2.  创建DatagramPacket,包含将要发送的信息 3.  创建DatagramSocket 4.  发送数据 服务器端 import java.io.IOException; import java.net.Datagram