`
b_l_east
  • 浏览: 639165 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java 代理使用及代理原理

 
阅读更多

今天再测试Socket编程时,无法连接外网。公司用的是Http的代理。上网搜索也没看太懂,所以花了大量时间来学习。看了HTTP和TCP协议的关系好,才有所明白。现在能通过Socket使用HTTP代理了,结果很简单,过程却好难。

 

1. 先简要说说HTTP和TCP(具体内容自行Google,资料很多很全),这里就讲讲要点:

HTTP:是应用层协议,是基于传输层协议的。

TCP: 是传输层协议,是基于网络层协议的。

IP: 是网络层协议。

一个TCP的连接要进行三次握手(就像转户口一样,不详说),HTTP只是一个应用协议,也就是相当于一个自定义协议,即其没有对底层的传输方式进行干涉,只是对数据内容格式进行了定义。打个比方,别人说“SB”(你的名字),你回答“是”,仅仅是内容格式,没有改变声音的传输方式(通过声波传送<网络硬件介质>,通过双方都能听懂的语言<TCP/IP>)。同理,FTP, Telnet也是一种应用层协议,打个比方对于FTP,别人说“SB",你回答“哎”,只是格式内容不同而已。

 

2. 认识到以上之后,我们再说说HTTP代理,从上可以理解,HTTP代理服务器就是这样一台机器:你把所有的HTTP请求(不管是想请求百度还是Google)都发到这个HTTP代理服务器,然后这个HTTP代理服务器请求你要访问的最终地址,把响应回传给你。这里还要注意它代理的是HTTP协议,而HTTP又是基于TCP的,也就是说这个服务器代理的是指定HTTP内容格式的TCP连接。再说下去也没意思了,看以下代码:

 

 

		//以下地址是代理服务器的地址
		Socket socket = new Socket("10.1.2.188", 80);
		//写与的内容就是遵循HTTP请求协议格式的内容,请求百度
		socket.getOutputStream().write(new String("GET http://www.baidu.com/ HTTP/1.1\r\n\r\n").getBytes());
		byte[] bs = new byte[1024];
		InputStream is = socket.getInputStream();
		int i;
		while ((i = is.read(bs)) > 0) {
			System.out.println(new String(bs, 0, i));
		}
		is.close();

 

当然在Java中,有Proxy代理上网的使用,此时使用URL(HTTP)就不涉及Socket(TCP)了,看如下代码

 

 

		//设置代理
		System.setProperty("http.proxySet", "true");
		System.setProperty("http.proxyHost", "10.1.2.188");
		System.setProperty("http.proxyPort", "80");
		
		//直接访问目的地址
		URL url = new URL("http://www.baidu.com");
		URLConnection con = url.openConnection();
		InputStreamReader isr = new InputStreamReader(con.getInputStream());
		char[] cs = new char[1024];
		int i = 0;
		while ((i = isr.read(cs)) > 0) {
			System.out.println(new String(cs, 0, i));
		}
		isr.close();

 

最后总结一下:

在使用HTTP代理的环境中,

如果使用Socket(TCP)连接外网,则直接连接代理服务器,然后在发送的HTTP请求中指明要转发到的外网网址。

如果使用URL(HTTP)连接外网,则需要设置HTTP代理参数或使用Proxy。

 

OK,明白以后可以随意使用了,看以下代码,使用NIO的Socket通过HTTP代理访问外网的例子:

 

		SocketChannel sc = SocketChannel.open(new InetSocketAddress("10.1.2.188", 80));
		
		sc.write(Charset.forName("utf8").encode("GET http://www.baidu.com/ HTTP/1.1\r\n\r\n"));
		
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		
		while (sc.read(buffer) != -1) {
			buffer.flip();
			System.out.println(Charset.forName("utf8").decode(buffer));
			buffer.clear();
		}
		sc.close();
 

 

《《以下是从摘自他人的博客》》:http://hi.baidu.com/splike/blog/item/ed2191d7c94360d1a144dfe3.html

Java Socket编程中加入代理
2010-06-02 11:12
有些时候我们的网络不能直接连接到外网需要使用http或是https或是socket代理来连接到外网这里是java使用代理连接到外网的一些方法,:方法一使用系统属性来完成代理设置这种方法比较简单但是不能对单独的连接来设置代理:
    public static void main(String[] args) {
        Properties prop = System.getProperties();
        // 设置http访问要使用的代理服务器的地址
        prop.setProperty("http.proxyHost""192.168.0.254");
        // 设置http访问要使用的代理服务器的端口
        prop.setProperty("http.proxyPort""8080");
        // 设置不需要通过代理服务器访问的主机,可以使用*通配符,多个地址用|分隔
        prop.setProperty("http.nonProxyHosts""localhost|192.168.0.*");
        // 设置安全访问使用的代理服务器地址与端口
        // 它没有https.nonProxyHosts属性,它按照http.nonProxyHosts 中设置的规则访问
        prop.setProperty("https.proxyHost""192.168.0.254");
        prop.setProperty("https.proxyPort""443");
        // 使用ftp代理服务器的主机、端口以及不需要使用ftp代理服务器的主机
        prop.setProperty("ftp.proxyHost""192.168.0.254");
        prop.setProperty("ftp.proxyPort""2121");
        prop.setProperty("ftp.nonProxyHosts""localhost|192.168.0.*");
        // socks代理服务器的地址与端口
        prop.setProperty("socksProxyHost""192.168.0.254");
        prop.setProperty("socksProxyPort""8000");
        // 设置登陆到代理服务器的用户名和密码
        Authenticator.setDefault(new MyAuthenticator("userName""Password"));
    }
    static class MyAuthenticator extends Authenticator {
        private String user = "";
        private String password = "";
        public MyAuthenticator(String user, String password) {
            this.user = user;
            this.password = password;
        }
        protected PasswordAuthentication getPasswordAuthentication() {
            returnnew PasswordAuthentication(userpassword.toCharArray());
        }
    }
方法二使用Proxy来对每个连接实现代理这种方法只能在jdk 1.5以上的版本使用(包含jdk1.5), 优点是可以单独的设置每个连接的代理缺点是设置比较麻烦:
    public static void main(String[] args) {
        try {
            URL url = new URL("http://www.baidu.com");
            // 创建代理服务器
            InetSocketAddress addr = new InetSocketAddress("192.168.0.254",
                    8080);
            // Proxy proxy = new Proxy(Proxy.Type.SOCKS, addr); // Socket 代理
            Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
            // 如果我们知道代理server的名字可以直接使用
            // 结束
            URLConnection conn = url.openConnection(proxy);
            InputStream in = conn.getInputStream();
            // InputStream in = url.openStream();
            String s = IOUtils.toString(in);
            System.out.println(s);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 

 

分享到:
评论
5 楼 xinglianxlxl 2017-11-10  
在使用HTTP代理的环境中,
如果使用Socket(TCP)连接外网,则直接连接代理服务器,然后在发送的HTTP请求中指明要转发到的外网网址。
如果使用URL(HTTP)连接外网,则需要设置HTTP代理参数或使用Proxy。


// 创建代理服务器
            InetSocketAddress addr = new InetSocketAddress("192.168.0.254",
                    8080);
            // Proxy proxy = new Proxy(Proxy.Type.SOCKS, addr); // Socket 代理
            Proxy proxy = new Proxy(Proxy.Type.HTTP, addr); // http 代理
            // 如果我们知道代理server的名字, 可以直接使用
            // 结束
            URLConnection conn = url.openConnection(proxy);

对我有用
4 楼 luoruiyuan 2015-10-19  
打个比方,别人说“SB”(你的名字),你回答“是”
3 楼 yinxin2745154 2012-09-17  
Hi,请问楼主,如何解决https代理?
2 楼 b_l_east 2012-05-14  
额,貌似你这里报的错是 消息格式问题:
         proxySocketout.write("CONNECT ebs.95559.com.cn:443 HTTP/1.0\n\n"); 
         proxySocketout.write("User-Agent: Java/1.6.0_10-rc2 \n\n"); 
         proxySocketout.write("Host: ebs.95559.com.cn \n\n"); 
         proxySocketout.write("Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\n\n"); 
         proxySocketout.write("GET   HTTP/1.0\n\n");

最后一个write应该在第一行才对吧("GET HTTP/1.0\n\n"应该放在第一行)
1 楼 clausewitzer 2012-04-16  
感谢楼主分享,想求教下socket用http代理访问https时  发送的报文格式应该是什么样的?
  //TODO:创建与代理的连接  
		 Socket proxySocket = new Socket("202.84.17.41",1080); 
		 BufferedWriter proxySocketout = new BufferedWriter(new OutputStreamWriter(proxySocket.getOutputStream()));
		 proxySocketout.write("CONNECT ebs.95559.com.cn:443 HTTP/1.0\n\n");
		 proxySocketout.write("User-Agent: Java/1.6.0_10-rc2 \n\n");
		 proxySocketout.write("Host: ebs.95559.com.cn \n\n");
		 proxySocketout.write("Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\n\n");
		 proxySocketout.write("GET   HTTP/1.0\n\n");
		 proxySocketout.flush();
		 //创建SSLSocket
	     sslSocket =(SSLSocket)sslSocketFactory.createSocket(proxySocket,"ebs.95559.com.cn",443 ,true);

//请求目标https数据
 OutputStream out = sslSocket.getOutputStream();
out.write("GET https://ebs.95559.com.cn/corporbank/es_logon.jsp HTTP/1.0\n\n");
out.flush(); 


但是后台会抛出
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
at com.sun.net.ssl.internal.ssl.InputRecord.handleUnknownRecord(InputRecord.java:523)
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:355)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:789)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1096)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:623)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
at java.io.OutputStream.write(OutputStream.java:58)
at com.xinhuanet.mblog.realname.test.Test6.doTest2(Test6.java:171)
at com.xinhuanet.mblog.realname.test.Test6.main(Test6.java:204)

相关推荐

    Java代理模式Java动态代理

    ### Java代理模式与Java动态代理详解 #### 一、代理模式概述 代理模式是一种软件设计模式,它在客户端和目标对象之间提供了一种间接层。这种模式的主要目的是控制客户端对目标对象的访问,并且可以在不修改原有...

    Java代理服务器程序

    总之,这个Java代理服务器程序涵盖了网络编程、HTTP协议解析、并发处理、缓存策略、安全通信和日志记录等多个方面,对深入理解这些Java技术以及网络原理有着极大的学习价值。通过研究这个项目,开发者可以提升自己在...

    Java动态代理(Spring Aop原理)

    Java动态代理是Java提供的一种在运行时创建代理对象的技术,它是通过实现InvocationHandler接口和使用Proxy类来实现的。在Spring框架中,AOP(面向切面编程)就是基于Java动态代理来完成的,用于实现横切关注点,如...

    Java写http代理服务器

    本主题将深入探讨如何使用Java语言来编写这样的代理服务器。以下是对这个主题的详细解析: 首先,理解HTTP代理服务器的基本原理是必要的。HTTP代理服务器作为客户端与目标服务器之间的中介,它接收客户端的HTTP请求...

    java动态代理机制分析及拓展

    Java 动态代理机制是Java语言提供的一种在运行时创建代理类和代理对象的机制,主要涉及`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口。动态代理通常用于实现AOP(面向切面编程)、事件...

    java动态代理 经典文章(word 2007格式的)

    - `Java动态代理模式.docx`可能详细讲解了动态代理模式的原理和实现,包括如何创建代理对象和实现`InvocationHandler`。 - `动态代理详解.docx`则可能深入讨论了Java动态代理的细节,包括实际应用场景和常见问题。...

    Java 动态代理和Cglib代理(二)

    当目标对象实现了至少一个接口时,我们可以使用`java.lang.reflect.Proxy`类来创建代理对象。这个代理对象会拦截调用并执行自定义逻辑。例如,在调用真实对象的方法之前或之后,我们可以添加额外的行为,如记录日志...

    java反射机制和动态代理的原理

    java反射机制和动态代理的原理,熟悉反射机制和动态代理

    java动态代理实例

    首先,我们需要了解Java动态代理的基本原理。在Java中,动态代理主要通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。`Proxy`类用于创建代理对象,而`InvocationHandler`接口...

    动态代理原理实例Demo

    Java动态代理是Java编程中一个非常重要的特性,它允许我们在运行时创建代理对象,这些代理对象可以代替原对象执行某些额外的操作,而无需修改原对象的代码。动态代理在AOP(面向切面编程)中广泛应用,如日志记录、...

    java三种方法实现代理模式(源码+jar包)

    总的来说,掌握这三种代理模式对于提升Java开发能力至关重要,尤其是在大型项目中,合理使用代理模式可以有效解耦代码,提高代码的可维护性和复用性。通过分析和实践提供的源码,你可以更深入地理解代理模式的工作...

    java实现的代理服务器

    在这个实例中,我们将深入探讨代理服务器的概念、工作原理以及如何使用Java来实现它。 首先,我们需要理解代理服务器的基本概念。代理服务器(Proxy Server)是一种特殊的网络服务器,它接收来自客户端的请求,并...

    Java动态代理资源包

    Java动态代理是Java编程中的一种重要技术,它允许我们在运行时创建对象的代理,以便在调用实际对象的方法之前和之后执行额外的操作。本资源包专注于CGLIB库,一个强大的代码生成库,用于实现Java动态代理。 CGLIB...

    java socket编写的上网代理

    在这个特定的项目中,开发者使用Java语言实现了代理服务器的功能,允许用户通过该代理来访问互联网。下面将详细解释相关知识点。 1. **Java Socket**: Java Socket是Java提供的网络编程接口,它提供了低级别的...

    java代理源码

    Java代理源码主要涉及到的是Java编程中的动态代理和网络代理技术。在Spring MVC框架下,开发者经常使用代理模式来扩展或增强对象的功能,同时,这里的"代理.war"文件表明这是一个Web应用程序,通常用于部署在如...

    java 简答可复用动态代理类

    1. **Java动态代理原理** - `Proxy`类是Java提供的动态代理的工厂,它可以根据一个接口生成实现了该接口的代理类的对象。这个代理类会动态地生成并实现接口的所有方法。 - `InvocationHandler`接口定义了一个处理...

    Java动态代理案例演示代码

    以上就是Java动态代理的基本概念和使用方式。在提供的压缩包文件中,可能包含了一个简单的示例,展示了如何创建和使用动态代理。通过阅读和理解这个例子,你可以更深入地掌握动态代理的实现细节。如果你对某个部分有...

    java网络代理源代码

    Java网络代理源代码是用于创建一个代理服务器的程序,它可以帮助开发者在调试和监控网络数据时获取必要的信息。这个源代码特别适用于理解如何利用Java的Socket编程实现网络代理功能。以下将详细介绍Java Socket和...

Global site tag (gtag.js) - Google Analytics