zoukankan      html  css  js  c++  java
  • UrlConnection连接和Socket连接的区别

    关于UrlConnection连接和Socket连接的区别,只知道其中的原理如下:
    抽象一点的说,Socket只是一个供上层调用的抽象接口,隐躲了传输层协议的细节。
    urlconnection 基于Http协议,Http协议是应用层协议,对传输层Tcp协议进行了封装,是无状态协议,不需要你往考虑线程、同步、状态治理等,内部是通过socket进行连接和收发数据的,不过一般在数据传输完成之后需要封闭socket连接。
    直接使用Socket进行网络通讯得考虑线程治理、客户状态监控等,但是不用发送头信息等,更省流量。


    并不知道我们经常使用的URLConnection 内部是怎么实现的,今天心血来潮以URL为出发点来探个究竟。
    以下面这段代码为出发点
    URL url = new URL("http://zhoujianghai.iteye.com");
    URLConnection conecttion = (URLConnection)url.openConnection();

    根据java.net.URL源码,一步步进行分析,
    new URL("www.javaeye.com")会调用URL(URL context, String spec, URLStreamHandler handler),
    此时context和handler是null。
    url.openConnection()调用的是strmHandler.openConnection(this);
    而strmHandler是URLStreamHandler接口的子类的实例。
    抽象类 URLStreamHandler 是所有流协议处理程序的通用超类,可以通过不同 protocol 的 URL 实例,产生 java.net.URLConnection 对象。
    由于context和handler是null,所以终极根据具体的协议调用URL类中的setupStreamHandler()方法对strmHandler进行初始化。

    下面分析 setupStreamHandler()方法内的代码。

    ?

    ?

    [java] view plain copy
     
    1. String packageList = AccessController.doPrivileged(new PriviAction<String>(  
    2.                         "java.protocol.handler.pkgs"));  

    ?

    ?
    首先通过java.protocol.handler.pkgs 来设置 URLStreamHandler 实现类的包路径,SUN 的 JDK 内部实现类均是在 sun.net.www.protocol. 包下。
    关于sun/net/www/protocol/http包下相关类的源码,可以访问:http://www.docjar.org/docs/api/sun/net/www/protocol/http/package-index.html


    PriviAction 部分源码:

    [java] view plain copy
     
    1. public PriviAction(String property) {  
    2.       action = GET_SYSTEM_PROPERTY;  
    3.     arg1 = property;  
    4.     }  
    5.   
    6. public T run() {  
    7.    switch (action) {  
    8.      case GET_SYSTEM_PROPERTY:  
    9.      return (T)System.getProperty((String) arg1, (String) arg2);  
    10.     case GET_SECURITY_PROPERTY:  
    11.      return (T)Security.getProperty((String) arg1);  
    12.      case GET_SECURITY_POLICY:  
    13.      return (T)Policy.getPolicy();  
    14.      case SET_ACCESSIBLE:  
    15.      ((AccessibleObject) arg1).setAccessible(true);  
    16.      }  
    17.      return null;  
    18.      }  
    19. PriviAction<T> 实现了 java.security.PrivilegedAction<T>接口,会执行run()方法。  
    20. 由action = GET_SYSTEM_PROPERTY;可知会执行代码:  
    [java] view plain copy
     
    1. (T)System.getProperty((String) arg1, (String) arg2);  
    [java] view plain copy
     
    1. System.getProperty方法调用成员变量Properties props的getProperty(key, def)方法;  
    2. 由于并未设置任何Properties,此处会返回默认值def。def的值是null。  
    3. 因此会继续执行下面的代码:  
    [java] view plain copy
     
    1. String className = "org.apache.harmony.luni.internal.net.www.protocol." + protocol   
    2. ".Handler";   
    3.         try {  
    4.             strmHandler = (URLStreamHandler) Class.forName(className)  
    5.                     .newInstance();  
    6.         } catch (IllegalAccessException e) {  
    7.         } catch (InstantiationException e) {  
    8.         } catch (ClassNotFoundException e) {  
    9.         }  
    10. 此时protocol是http协议,从而根据协议 (protocol) 获得协议 URLStreamHandler 对象。  
    11. 所以此时通过反射机制创建org.apache.harmony.luni.internal.net.www.protocol.http.Handler类的实例。  
    12. 此时回到上面提到的 strmHandler.openConnection(this);  

    将调用下面的Handler类的实例的openConnection(URL u)方法。


    @Override

    [java] view plain copy
     
    1. protected URLConnection openConnection(URL u) throws IOException {  
    2.     return new HttpURLConnectionImpl(u, getDefaultPort());  
    3. }  
    4.   
    5.   
    6. ected URLConnection openConnection(URL u, Proxy proxy)  
    7.         throws IOException {  
    8.     if (null == u || null == proxy) {  
    9.         throw new IllegalArgumentException(Messages.getString("luni.1B"));   
    10.     }  
    11.     return new HttpURLConnectionImpl(u, getDefaultPort(), proxy);  
    12. }  


    此时会创建HttpURLConnectionImpl对象。HttpURLConnectionImpl是java.net.HttpURLConnection的子类。 该类有个成员变量HttpConnection connection;
    这才是我们要找的,该类对Socket进行了封装。


    HttpConnection 部分源码如下:


     private Socket socket;

    [java] view plain copy
     
    1.          private SSLSocket sslSocket;  
    2.         
    3.          private InputStream inputStream;  
    4.           private OutputStream outputStream;  
    5.          private InputStream sslInputStream;  
    6.          private OutputStream sslOutputStream;  
    7.         
    8.          private HttpConfiguration config;  
    9.         
    10.           public HttpConnection(HttpConfiguration config, int connectTimeout) throws IOException {  
    11.               this.config = config;  
    12.              String hostName = config.getHostName();  
    13.              int hostPort = config.getHostPort();  
    14.               Proxy proxy = config.getProxy();  
    15.               if(proxy == null || proxy.type() == Proxy.Type.HTTP) {  
    16.                  socket = new Socket();  
    17.               } else {  
    18.                   socket = new Socket(proxy);  
    19.               }  
    20.               socket.connect(new InetSocketAddress(hostName, hostPort), connectTimeout);  
    21.           }  
    22.   
    23.   
    24. 现在UrlConnection连接和Socket连接的区别应该十分清楚了吧。  
    25. 使用UrlConnection比直接使用Socket要简单的多,不用关心状态和线程治理。  
    26. UrlConnection基于Http协议,只是进行了封装,添加了一些额外规则(如头信息),本质上也是建立TCP连接,利用Socket实现连接和传输数据的,不过我们一般每次请求完数据后都会实现finally方法,在该方法里封闭连接。  

    四周是相关类的源码。
    可以往这个链接地址查找更多类的源码:
    http://www.docjar.com/projects/apache-harmony-6.0-src-r917296-snapshot-code.html

  • 相关阅读:
    15个新鲜出炉的 Photoshop 文本效果教程
    10个美丽的例子,插图在网页设计中的应用
    分享8个非常时髦的翻页特效(附代码片段)
    【Vue课堂】Vue.js 父子组件之间通信的十种方式
    Tippy.js – 轻量的 Javascript Tooltip 工具库
    12个美丽的网站与受到日出启发的配色方案
    精选:3个可以下载免费的高质量照片的网站
    nativefier
    Mark Text
    Puppeteer
  • 原文地址:https://www.cnblogs.com/csguo/p/7542340.html
Copyright © 2011-2022 走看看