欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java中的代理原理及代理使用示例

程序员文章站 2024-03-03 17:36:22
今天再测试socket编程时,无法连接外网。公司用的是http的代理。上网搜索也没看太懂,所以花了大量时间来学习。看了http和tcp协议的关系好,才有所明白。现在能通过s...

今天再测试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(); 

java socket编程中加入代理示例

有些时候我们的网络不能直接连接到外网, 需要使用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("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();
        }
    }