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(user,?password.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(" //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();