今天再测试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连接。再说下去也没意思了,看以下代码:

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

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

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

最后总结一下:

在使用HTTP代理的环境中,

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

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

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

  1. SocketChannel sc = SocketChannel.open(new InetSocketAddress("10.1.2.188", 80));
  2. sc.write(Charset.forName("utf8").encode("GET http://www.baidu.com/ HTTP/1.1\r\n\r\n"));
  3. ByteBuffer buffer = ByteBuffer.allocate(1024);
  4. while (sc.read(buffer) != -1) {
  5. buffer.flip();
  6. System.out.println(Charset.forName("utf8").decode(buffer));
  7. buffer.clear();
  8. }
  9. 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("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();
        }
    }

Java 代理使用及代理原理的更多相关文章

  1. Java之美[从菜鸟到高手演练]之JDK动态代理的实现及原理

    Java之美[从菜鸟到高手演练]之JDK动态代理的实现及原理 JDK动态代理的实现及原理 作者:二青 邮箱:xtfggef@gmail.com     微博:http://weibo.com/xtfg ...

  2. java中代理,静态代理,动态代理以及spring aop代理方式,实现原理统一汇总

    若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. ...

  3. java面试题(杨晓峰)---第六讲谈谈动态代理是基于什么原理?

    我在编译时不知道,而在运行时知道,那么肯定在运行时给了提示,这个提示就是额外功.好处是可以重复利用相同代码. 代理模式:通过代理静默的解决一些与业务无关的问题,例如远程,安全,事物,日志,资源关闭,. ...

  4. Java设计模式——代理模式实现及原理

    简介 Java编程的目标是实现现实不能完成的,优化现实能够完成的,是一种虚拟技术.生活中的方方面面都可以虚拟到代码中.代理模式所讲的就是现实生活中的这么一个概念:中介. 代理模式的定义:给某一个对象提 ...

  5. 重学 Java 设计模式:实战代理模式「模拟mybatis-spring中定义DAO接口,使用代理类方式操作数据库原理实现场景」

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 难以跨越的瓶颈期,把你拿捏滴死死的! 编程开发学习过程中遇到的瓶颈期,往往是由于看不 ...

  6. java运行原理、静态代理和动态代理区分

    1.java的编译和运行原理: ■ 编译:将源文件 .java 文件,通过编译器(javac 命令) 编译成 字节码文件 .class 文件. ■ 运行,通过类加载器(以二进制流形式)把字节码加载进J ...

  7. java反射和动态代理实现与原理详细分析

    关于Java中的动态代理,我们首先需要了解的是一种常用的设计模式--代理模式,而对于代理,根据创建代理类的时间点,又可以分为静态代理和动态代理. 一.代理模式    代理模式是常用的java设计模式, ...

  8. java静态和动态代理原理

    一.代理概念 为某个对象提供一个代理,以控制对这个对象的访问. 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代.代理类负责请求的预处理.过滤.将请求分派给委托类 ...

  9. Java JDK 动态代理使用及实现原理分析

    转载:http://blog.csdn.net/jiankunking   一.什么是代理? 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理 ...

  10. Java 动态代理是基于什么原理

    动态代理 ①动态代理概念理解 动态代理是一种方便运行时动态构建代理.动态处理代理方法调用的机制,很多场景都利用类似机制做到的,比如用来包装RPC调用.面向切面的变成(AOP) 实现动态代理的方式很多, ...

随机推荐

  1. Java:concurrent包下面的Map接口框架图(ConcurrentMap接口、ConcurrentHashMap实现类)

    Java集合大致可分为Set.List和Map三种体系,其中Set代表无序.不可重复的集合:List代表有序.重复的集合:而Map则代表具有映射关系的集合.Java 5之后,增加了Queue体系集合, ...

  2. PHP文件锁定写入实例分享

    PHP文件锁定写入实例解析. 原文地址:http://www.jbxue.com/article/23118.html PHP文件写入方法,以应对多线程写入,具体代码: function file_w ...

  3. 坊间流传着的关于谷歌大牛Jeff Dean的传说

    Jeff Dean,Google的软件架构天才.Google大型并发编程框架Map/Reduce作者. 在Google,公司最顶尖的编程高手Jeff Dean曾发明过一种先进的方法,该方法可以让一个程 ...

  4. Atitit 个人信息数据文档知识分类

    Atitit 个人信息数据文档知识分类 1.1. 知识分类法,参照图书分类法 1 2. Attilax知识分类 2 2.1. 公共文档(一般技术资料,通过标题可以网上搜索到的) 2 2.2. sum ...

  5. BNUOJ 34982 Beautiful Garden

    BNUOJ 34982 Beautiful Garden 题目地址:BNUOJ 34982 题意:  看错题意纠结了好久... 在坐标轴上有一些树,如今要又一次排列这些树,使得相邻的树之间间距相等.  ...

  6. nodejs中的框架介绍

    Sequelize 关系型数据库对象模型映射框架 mongoose 非关系型数据库文档模型映射框架

  7. 每日英语:Google Scraps Plan to Build Hong Kong Data Center

    Internet giant Google Inc. has scrapped a plan to build its own data center in Hong Kong and will in ...

  8. linux命令(52):usermod 修改账户信息,groupmod

    usermod: usermod [options] user_name usermod 命令修改系统帐户文件来反映通过命令行指定的变化 选项(options) -a|--append  ##把用户追 ...

  9. (原)ubuntu下cadvisor+influxdb+grafana+supervisord监控主机和docker的containers

    ubuntu下cadvisor+influxdb+grafana+supervisord监控主机和docker的containers(运行在主机上) 适用于类ubuntu系统.amd64. 1. in ...

  10. 21、uwp UI自动化测试(WinAppDriver)

    使用 UI自动化测试的好处就是在代码逻辑中写好 case 后,来实现 “一劳永逸” 的作用,并且自动化测试能够模拟人工达不到要求,比如快速切换页面.快速点击按钮等,对于提高软件的稳定性很有帮助. 安装 ...