HttpURLConnection源码分析

  • 本文概述

    从源码角度理解HttpURLConnection是怎么一步步封装底层socket调用的。

  • HttpURLConnection使用回顾

    我们先来回顾一下它的用法:

    new Thread(() -> {
         
        HttpURLConnection connection = null;
        BufferedReader reader = null;
        try{
         
            URL url = new URL("https://www.baidu.com");//新建URL
            connection = (HttpURLConnection)url.openConnection();//发起网络请求
            connection.setRequestMethod("GET");//请求方式
            connection.setConnectTimeout(8000);//连接最大时间
            connection.setReadTimeout(8000);//读取最大时间
            InputStream in = connection.getInputStream();
            reader = new BufferedReader(new InputStreamReader(in));//写入reader
            StringBuilder response = new StringBuilder();
            String line;
            while((line = reader.readLine()) != null){
         
                response.append(line);
            }
            //更新ui
            showResponse(response.toString());
        }catch (Exception e){
         
            e.printStackTrace();
        }finally {
         
            if(reader != null){
         
                try{
         
                    reader.close();
                }catch (IOException e){
         
                    e.printStackTrace();
                }
            }
            if(connection != null){
         
                connection.disconnect();
            }
        }
    }).start();
    

    接下来从源码角度研究一下它的原理。

  • 源码分析

    首先构造一个URL对象,然后调用它的openConnection(),进去发现调用的是handler.openConnection(URL url),handler是怎么创建的呢?看一下URL对象的构造方法就会发现一些线索,构造方法最终会走到this(context, spec, null):

    public URL(URL context, String spec, URLStreamHandler handler)
        throws MalformedURLException
    {
         
        String original = spec;
        int i, limit, c;
        int start = 0;
        String newProtocol = null;
        boolean aRef=false;
        boolean isRelative = false;
    
        // Check for permission to specify a handler
        if (handler != null) {
         
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
         
                checkSpecifyHandler(sm);
            }
        }
    
        try {
         
            limit = spec.length();
            while ((limit > 0) && (spec.charAt(limit - 1) <= ' ')) {
         
                limit--;        //eliminate trailing whitespace
            }
            while ((start < limit) && (spec.charAt(start) <= ' ')) {
         
                start++;        // eliminate leading whitespace
            }
    
            if (spec.regionMatches(true, start, "url:", 0, 4)) {
         
                start += 4;
            }
            if (start < spec.length() && spec.charAt(start) == '#') {
         
                /* we're assuming this is a ref relative to the context URL.
                 * This means protocols cannot start w/ '#', but we must parse
                 * ref URL's like: "hello:there" w/ a ':' in them.
                 */
                aRef=true;
            }
            for (i = start ; !aRef && (i < limit) &&
                     ((c = spec.charAt(i)) != '/') ; i++) {
         
                if (c == ':') {
         
    
                    String s = spec.substring(start, i).toLowerCase();
                    if (isValidProtocol(s)) {
         
                        newProtocol = s;
                        start = i + 1;
                    }
                    break;
                }
            }
    
            // Only use our context if the protocols match.
            protocol = newProtocol;
            if ((context != null) && ((newProtocol == null) ||
                            newProtocol.equalsIgnoreCase(context.protocol))) {
         
                // inherit the protocol handler from the context
                // if not specified to the constructor
                if (handler == null) {
         
                    handler = context.handler;
                }
    
                // If the context is a hierarchical URL scheme and the spec
                // contains a matching scheme then maintain backwards
                // compatibility and treat it as if the spec didn't contain
                // the scheme; see 5.2.3 of RFC2396
                if (context.path != null && context.path.startsWith("/"))
                    newProtocol = null;
    
                if (newProtocol == null) {
         
                    protocol = context.protocol;
                    authority = context.authority;
                    userInfo = context.userInfo;
                    host = context.host;
                    port = context.port;
                    file = context.file;
                    path = context.path;
                    isRelative = true;
                }
            }
    
            if (protocol == null) {
         
                throw new MalformedURLException("no protocol: "+original);
            }
    
            // Get the protocol handler if not specified or the protocol
            // of the context could not be used
            if (handler 
Android网络连接源码分析主要涉及到Android系统中网络连接的相关实现和机制。下面是Android网络连接的源码分析: 1. 网络连接管理类:Android中的网络连接管理由ConnectivityManager类负责。该类提供了获取网络状态、监听网络状态变化等功能。其源码位于frameworks/base/core/java/android/net/ConnectivityManager.java。 2. 网络请求类:Android中的网络请求由HttpClient或HttpURLConnection实现。在Android 6.0及以上版本中,Google推荐使用HttpURLConnectionHttpClient的源码位于frameworks/base/core/java/org/apache/http/impl/client/DefaultHttpClient.javaHttpURLConnection源码位于libcore/luni/src/main/java/java/net/HttpURLConnection.java。 3. 网络请求处理类:Android中的网络请求处理由AsyncTask或者Thread实现。AsyncTask是一个封装了线程池和Handler的异步任务类,用于在后台执行耗时操作,并在主线程更新UI。其源码位于frameworks/base/core/java/android/os/AsyncTask.java。 4. 网络请求结果处理类:Android中的网络请求结果处理由Handler或者Callback实现。Handler用于在主线程中处理异步任务的结果,Callback则是一种回调机制,用于在异步任务完成后执行相应的操作。 5. 网络缓存类:Android中的网络缓存由DiskLruCache或者LruCache实现。DiskLruCache用于将网络请求结果缓存到本地磁盘,LruCache则是一种内存缓存机制,用于缓存网络请求结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值