`

HttpUrlConnection底层实现和关于java host绑定ip即时生效的设置及分析

    博客分类:
  • java
 
阅读更多

 

最近有个需求需要对于获取URL页面进行host绑定并且立即生效,在java里面实现可以用代理服务器来实现:因为在测试环境下可能需要通过绑定来访问测试环境的应用

实现代码如下:

 

    public static String getResponseText(String queryUrl,String host,String ip) { //queryUrl,完整的urlhostip需要绑定的hostip

       InputStream is = null;

       BufferedReader br = null;

       StringBuffer res = new StringBuffer();

       try {

           HttpURLConnection httpUrlConn = null;

           URL url = new URL(queryUrl);

           if(ip!=null){

               String str[] = ip.split("\\.");

               byte[] b =new byte[str.length];

               for(int i=0,len=str.length;i<len;i++){

                   b[i] = (byte)(Integer.parseInt(str[i],10));

               }

                Proxy proxy = new Proxy(Proxy.Type.HTTP,

                new InetSocketAddress(InetAddress.getByAddress(b), 80));  //b是绑定的ip,生成proxy代理对象,因为http底层是socket实现,

                httpUrlConn = (HttpURLConnection) url

                .openConnection(proxy);

           }else{

                httpUrlConn = (HttpURLConnection) url

                        .openConnection(); 

           }

           httpUrlConn.setRequestMethod("GET");

           httpUrlConn.setDoOutput(true);

           httpUrlConn.setConnectTimeout(2000);

           httpUrlConn.setReadTimeout(2000);

           httpUrlConn.setDefaultUseCaches(false);

           httpUrlConn.setUseCaches(false);

 

           is = httpUrlConn.getInputStream();

 

 

那么底层对于proxy对象到底是怎么处理,底层的socket实现到底怎么样,带着这个疑惑看了下jdkrt.jar对于这块的处理

httpUrlConn = (HttpURLConnection) url.openConnection(proxy)

 

java.net.URL类里面的openConnection方法:

public URLConnection openConnection(Proxy proxy){

   …

   return handler.openConnection(this, proxy); Handlersun.net.www.protocol.http.Handler.java类,继承java.net. URLStreamHandler.java类,用来处理http连接请求响应的。

}

 

Handler的方法:

protected java.net.URLConnection openConnection(URL u, Proxy p)

        throws IOException {

        return new HttpURLConnection(u, p, this);

    }

 

只是简单的生成sun.net.www.protocl.http.HttpURLConnection对象,并进行初始化

protected HttpURLConnection(URL u, Proxy p, Handler handler) {

        super(u);

        requests = new MessageHeader();  请求头信息生成类

        responses = new MessageHeader(); 响应头信息解析类

        this.handler = handler; 

        instProxy = p;  代理服务器对象

        cookieHandler = (CookieHandler)java.security.AccessController.doPrivileged(

            new java.security.PrivilegedAction() {

            public Object run() {

                return CookieHandler.getDefault();

            }

        });

        cacheHandler = (ResponseCache)java.security.AccessController.doPrivileged(

            new java.security.PrivilegedAction() {

            public Object run() {

                return ResponseCache.getDefault();

            }

        });

    }

  

 

最终在httpUrlConn.getInputStream();才进行socket连接,发送http请求,解析http响应信息。具体过程如下:

 

sun.net.www.protocl.http.HttpURLConnection.javagetInputStream方法:

 

public synchronized InputStream getInputStream() throws IOException {

   

     ...socket连接

     connect();

     ...

     ps = (PrintStream)http.getOutputStream(); 获得输出流,打开连接之后已经生成。

 

       if (!streaming()) {

             writeRequests();  输出http请求头信息

       }

     ...

     http.parseHTTP(responses, pi, this);  解析响应信息

                if(logger.isLoggable(Level.FINEST)) {

                    logger.fine(responses.toString());

                }

                inputStream = http.getInputStream();  获得输入流

}

 

其中connect()调用方法链:

plainConnect(){

...

                Proxy p = null;

                if (sel != null) {

                    URI uri = sun.net.www.ParseUtil.toURI(url);

                    Iterator<Proxy> it = sel.select(uri).iterator();

                    while (it.hasNext()) {

                        p = it.next();

                        try {

                            if (!failedOnce) {

                                http = getNewHttpClient(url, p, connectTimeout);

...

}

 

getNewHttpClient(){

...

        return HttpClient.New(url, p, connectTimeout, useCache);

...

}

 

下面跟进去最终建立socket连接的代码:

sun.net.www.http.HttpClient.javaopenServer()方法建立socket连接:

 

    protected synchronized void openServer() throws IOException {

            ...

            if ((proxy != null) && (proxy.type() == Proxy.Type.HTTP)) {

                sun.net.www.URLConnection.setProxiedHost(host);

                if (security != null) {

                    security.checkConnect(host, port);

                }

                privilegedOpenServer((InetSocketAddress) proxy.address());最终socket连接的是设置的代理服务器的地址,

            ...

}

 

    private synchronized void privilegedOpenServer(final InetSocketAddress server)

         throws IOException

    {

        try {

            java.security.AccessController.doPrivileged(

                new java.security.PrivilegedExceptionAction() {

                public Object run() throws IOException {

                    openServer(server.getHostName(), server.getPort());  注意openserver函数  这里的servergetHostName是设置的代理服务器,(ip或者hostname,如果是host绑定设置的代理服务器的ip,那么这里getHostName出来的就是ip地址,可以去查看InetSocketAddress类的getHostName方法)

                    return null;

                }

            });

        } catch (java.security.PrivilegedActionException pae) {

            throw (IOException) pae.getException();

        }

    }

 

   public void openServer(String server, int port) throws IOException {

        serverSocket = doConnect(server, port);  生成的Socket连接对象

        try {

            serverOutput = new PrintStream(

                new BufferedOutputStream(serverSocket.getOutputStream()),

                                         false, encoding);   生成输出流,

        } catch (UnsupportedEncodingException e) {

            throw new InternalError(encoding+" encoding not found");

        }

        serverSocket.setTcpNoDelay(true);

    }

 

 

protected Socket doConnect (String server, int port)

    throws IOException, UnknownHostException {

        Socket s;

        if (proxy != null) {

            if (proxy.type() == Proxy.Type.SOCKS) {

                s = (Socket) AccessController.doPrivileged(

                               new PrivilegedAction() {

                                   public Object run() {

                                       return new Socket(proxy);

                                   }});

            } else

                s = new Socket(Proxy.NO_PROXY);

        } else

            s = new Socket();

        // Instance specific timeouts do have priority, that means

        // connectTimeout & readTimeout (-1 means not set)

        // Then global default timeouts

        // Then no timeout.

        if (connectTimeout >= 0) {

            s.connect(new InetSocketAddress(server, port), connectTimeout);

        } else {

            if (defaultConnectTimeout > 0) {

                s.connect(new InetSocketAddress(server, port), defaultConnectTimeout);//连接到代理服务器,看下面Socket类的connect方法代码

            } else {

                s.connect(new InetSocketAddress(server, port));

            }

        }

        if (readTimeout >= 0)

            s.setSoTimeout(readTimeout);

        else if (defaultSoTimeout > 0) {

            s.setSoTimeout(defaultSoTimeout);

        }

        return s;

}

 

上面的new InetSocketAddress(server, port)这里会涉及到java DNS cache的处理,

 

      public InetSocketAddress(String hostname, int port) {

        if (port < 0 || port > 0xFFFF) {

            throw new IllegalArgumentException("port out of range:" + port);

        }

        if (hostname == null) {

            throw new IllegalArgumentException("hostname can't be null");

        }

        try {

            addr = InetAddress.getByName(hostname);  //这里会有java DNS缓存的处理,先从缓存取hostname绑定的ip地址,如果取不到再通过OSDNS cache机制去取,取不到再从DNS服务器上取。

        } catch(UnknownHostException e) {

            this.hostname = hostname;

            addr = null;

        }

        this.port = port;

    }

 

 

 

当然最终的Socket.javaconnect方法

java.net.socket

            

   public void connect(SocketAddress endpoint, int timeout) throws IOException {

        if (endpoint == null)

           

        if (timeout < 0)

          throw new IllegalArgumentException("connect: timeout can't be negative");

 

        if (isClosed())

            throw new SocketException("Socket is closed");

 

        if (!oldImpl && isConnected())

            throw new SocketException("already connected");

 

        if (!(endpoint instanceof InetSocketAddress))

            throw new IllegalArgumentException("Unsupported address type");

 

        InetSocketAddress epoint = (InetSocketAddress) endpoint;

 

        SecurityManager security = System.getSecurityManager();

        if (security != null) {

            if (epoint.isUnresolved())

                security.checkConnect(epoint.getHostName(),

                                      epoint.getPort());

            else

                security.checkConnect(epoint.getAddress().getHostAddress(),

                                      epoint.getPort());

        }

        if (!created)

            createImpl(true);

        if (!oldImpl)

            impl.connect(epoint, timeout);

        else if (timeout == 0) {

            if (epoint.isUnresolved())  //如果没有设置SocketAddressip地址,则用域名去访问

                impl.connect(epoint.getAddress().getHostName(),

                             epoint.getPort());

            else

                impl.connect(epoint.getAddress(), epoint.getPort());  最终socket连接的是设置的SocketAddressip地址,

        } else

            throw new UnsupportedOperationException("SocketImpl.connect(addr, timeout)");

        connected = true;

        /*

         * If the socket was not bound before the connect, it is now because

         * the kernel will have picked an ephemeral port & a local address

         */

        bound = true;

    }

 

 

 

我们再看下通过socket来发送HTTP请求的处理代码,也就是sun.net.www.protocl.http.HttpURLConnection.javagetInputStream方法中调用的writeRequests()方法: 

private void writeRequests() throws IOException {  这段代码就是封装http请求的头请求信息,通过socket发送出去

        /* print all message headers in the MessageHeader

         * onto the wire - all the ones we've set and any

         * others that have been set

         */

        // send any pre-emptive authentication

        if (http.usingProxy) {

            setPreemptiveProxyAuthentication(requests);

        }

        if (!setRequests) {

 

            /* We're very particular about the order in which we

             * set the request headers here.  The order should not

             * matter, but some careless CGI programs have been

             * written to expect a very particular order of the

             * standard headers.  To name names, the order in which

             * Navigator3.0 sends them.  In particular, we make *sure*

             * to send Content-type: <> and Content-length:<> second

             * to last and last, respectively, in the case of a POST

             * request.

             */

            if (!failedOnce)

                requests.prepend(method + " " + http.getURLFile()+" "  +

                                 httpVersion, null);

            if (!getUseCaches()) {

                requests.setIfNotSet ("Cache-Control", "no-cache");

                requests.setIfNotSet ("Pragma", "no-cache");

            }

            requests.setIfNotSet("User-Agent", userAgent);

            int port = url.getPort();

            String host = url.getHost();

            if (port != -1 && port != url.getDefaultPort()) {

                host += ":" + String.valueOf(port);

            }

            requests.setIfNotSet("Host", host);

            requests.setIfNotSet("Accept", acceptString);

 

            /*

             * For HTTP/1.1 the default behavior is to keep connections alive.

             * However, we may be talking to a 1.0 server so we should set

             * keep-alive just in case, except if we have encountered an error

             * or if keep alive is disabled via a system property

             */

 

            // Try keep-alive only on first attempt

            if (!failedOnce && http.getHttpKeepAliveSet()) {

                if (http.usingProxy) {

                    requests.setIfNotSet("Proxy-Connection", "keep-alive");

                } else {

                    requests.setIfNotSet("Connection", "keep-alive");

                }

            } else {

                /*

                 * RFC 2616 HTTP/1.1 section 14.10 says:

                 * HTTP/1.1 applications that do not support persistent

                 * connections MUST include the "close" connection option

                 * in every message

                 */

                requests.setIfNotSet("Connection", "close");

            }

            // Set modified since if necessary

            long modTime = getIfModifiedSince();

            if (modTime != 0 ) {

                Date date = new Date(modTime);

                //use the preferred date format according to RFC 2068(HTTP1.1),

                // RFC 822 and RFC 1123

                SimpleDateFormat fo =

                  new SimpleDateFormat ("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);

                fo.setTimeZone(TimeZone.getTimeZone("GMT"));

                requests.setIfNotSet("If-Modified-Since", fo.format(date));

            }

            // check for preemptive authorization

            AuthenticationInfo sauth = AuthenticationInfo.getServerAuth(url);

            if (sauth != null && sauth.supportsPreemptiveAuthorization() ) {

                // Sets "Authorization"

                requests.setIfNotSet(sauth.getHeaderName(), sauth.getHeaderValue(url,method));

                currentServerCredentials = sauth;

            }

 

            if (!method.equals("PUT") && (poster != null || streaming())) {

                requests.setIfNotSet ("Content-type",

                        "application/x-www-form-urlencoded");

            }

 

            if (streaming()) {

                if (chunkLength != -1) {

                    requests.set ("Transfer-Encoding", "chunked");

                } else {

                    requests.set ("Content-Length", String.valueOf(fixedContentLength));

                }

            } else if (poster != null) {

                /* add Content-Length & POST/PUT data */

                synchronized (poster) {

                    /* close it, so no more data can be added */

                    poster.close();

                    requests.set("Content-Length",

                                 String.valueOf(poster.size()));

                }

            }

 

            // get applicable cookies based on the uri and request headers

            // add them to the existing request headers

            setCookieHeader();

}

 

 

再来看看把socket响应信息解析为http的响应信息的代码:

sun.net.www.http.HttpClient.javaparseHTTP方法:

private boolean parseHTTPHeader(MessageHeader responses, ProgressSource pi, HttpURLConnection httpuc)

    throws IOException {

        /* If "HTTP/*" is found in the beginning, return true.  Let

         * HttpURLConnection parse the mime header itself.

         *

         * If this isn't valid HTTP, then we don't try to parse a header

         * out of the beginning of the response into the responses,

         * and instead just queue up the output stream to it's very beginning.

         * This seems most reasonable, and is what the NN browser does.

         */

 

        keepAliveConnections = -1;

        keepAliveTimeout = 0;

 

        boolean ret = false;

        byte[] b = new byte[8];

 

        try {

            int nread = 0;

            serverInput.mark(10);

            while (nread < 8) {

                int r = serverInput.read(b, nread, 8 - nread);

                if (r < 0) {

                    break;

                }

                nread += r;

            }

            String keep=null;

            ret = b[0] == 'H' && b[1] == 'T'

                    && b[2] == 'T' && b[3] == 'P' && b[4] == '/' &&

                b[5] == '1' && b[6] == '.';

            serverInput.reset();

            if (ret) { // is valid HTTP - response started w/ "HTTP/1."

                responses.parseHeader(serverInput);

 

                // we've finished parsing http headers

                // check if there are any applicable cookies to set (in cache)

                if (cookieHandler != null) {

                    URI uri = ParseUtil.toURI(url);

                    // NOTE: That cast from Map shouldn't be necessary but

                    // a bug in javac is triggered under certain circumstances

                    // So we do put the cast in as a workaround until

                    // it is resolved.

                    if (uri != null)

                        cookieHandler.put(uri, (Map<java.lang.String,java.util.List<java.lang.String>>)responses.getHeaders());

                }

 

                /* decide if we're keeping alive:

                 * This is a bit tricky.  There's a spec, but most current

                 * servers (10/1/96) that support this differ in dialects.

                 * If the server/client misunderstand each other, the

                 * protocol should fall back onto HTTP/1.0, no keep-alive.

                 */

                if (usingProxy) { // not likely a proxy will return this

                    keep = responses.findValue("Proxy-Connection");

                }

                if (keep == null) {

                    keep = responses.findValue("Connection");

                }

                if (keep != null && keep.toLowerCase().equals("keep-alive")) {

                    /* some servers, notably Apache1.1, send something like:

                     * "Keep-Alive: timeout=15, max=1" which we should respect.

                     */

                    HeaderParser p = new HeaderParser(

                            responses.findValue("Keep-Alive"));

                    if (p != null) {

                        /* default should be larger in case of proxy */

                        keepAliveConnections = p.findInt("max", usingProxy?50:5);

                        keepAliveTimeout = p.findInt("timeout", usingProxy?60:5);

                    }

                } else if (b[7] != '0') {

                    /*

                     * We're talking 1.1 or later. Keep persistent until

                     * the server says to close.

                     */

                    if (keep != null) {

                        /*

                         * The only Connection token we understand is close.

                         * Paranoia: if there is any Connection header then

                         * treat as non-persistent.

                         */

                        keepAliveConnections = 1;

                    } else {

                        keepAliveConnections = 5;

                    }

                }

……

}

 

 

对于java.net包的httpftp等各种协议的底层实现,可以参考rt.jar下面的几个包的代码:

sun.net.www.protocl下的几个包。

 

 

http client中也可以设置代理

               HostConfiguration conf = new HostConfiguration();

               conf.setHost(host);

               conf.setProxy(ip, 80);

               statusCode = httpclient.executeMethod(conf,getMethod);

 

httpclient自己也是基于socket封装的http处理的库。底层代理的实现是一样的。

 

 

另外一种不设置代理,通过反射修改InetAddresscache也是ok的。但是这种方法非常不推荐,不要使用,因为对于proxy代理服务器概念了解不清楚,最开始还使用这种方法,

public static void jdkDnsNoCache(final String host, final String ip)

           throws SecurityException, NoSuchFieldException,

           IllegalArgumentException, IllegalAccessException {

       if (StringUtils.isBlank(host)) {

           return;

       }

       final Class clazz = java.net.InetAddress.class;

       final Field cacheField = clazz.getDeclaredField("addressCache");

       cacheField.setAccessible(true);

       final Object o = cacheField.get(clazz);

       Class clazz2 = o.getClass();

       final Field cacheMapField = clazz2.getDeclaredField("cache");

       cacheMapField.setAccessible(true);

       final Map cacheMap = (Map) cacheMapField.get(o);

       AccessController.doPrivileged(new PrivilegedAction() {

           public Object run() {

              try {

                  synchronized (o) {// 同步是必须的,因为o可能会有多个线程同时访问修改。

                     // cacheMap.clear();//这步比较关键,用于清除原来的缓存

//                   cacheMap.remove(host);

                     if (!StringUtils.isBlank(ip)) {

                         InetAddress inet = InetAddress.getByAddress(host,IPUtil.int2byte(ip));

                         InetAddress addressstart = InetAddress.getByName(host);

                         Object cacheEntry = cacheMap.get(host);

                         cacheMap.put(host,newCacheEntry(inet,cacheEntry));

//                       cacheMap.put(host,newCacheEntry(newInetAddress(host, ip)));

                     }else{

                         cacheMap.remove(host);

                     }

//                   System.out.println(getStaticProperty(

//                          "java.net.InetAddress", "addressCacheInit"));

                     // System.out.println(invokeStaticMethod("java.net.InetAddress","getCachedAddress",new

                     // Object[]{host}));

                  }

              } catch (Throwable te) {

                  throw new RuntimeException(te);

              }

              return null;

           }

       });

       final Map cacheMapafter = (Map) cacheMapField.get(o);

       System.out.println(cacheMapafter);

 

    }

 

关于java中对于DNS的缓存设置可以参考:

1.${java_home}/jre/lib/secuiry/java.secuiry文件,修改下面为 

  networkaddress.cache.negative.ttl=0   DNS解析不成功的缓存时间

networkaddress.cache.ttl=0    DNS解析成功的缓存的时间

2.jvm启动时增加下面两个启动环境变量

  -Dsun.net.inetaddr.ttl=0

      -Dsun.net.inetaddr.negative.ttl=0

 

 

如果在java程序中使用,可以这么设置设置:

    java.security.Security.setProperty("networkaddress.cache.ttl" , "0");

        java.security.Security.setProperty("networkaddress.cache.negative.ttl" , "0");

 

   还有几篇文档链接可以查看:

       http://www.rgagnon.com/javadetails/java-0445.html

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6247501

 

  linux下关于OS DNS设置的几个文件是

/etc/resolve.conf

/etc/nscd.conf

/etc/nsswitch.conf

 

http://www.linuxfly.org/post/543/

http://linux.die.net/man/5/nscd.conf

http://www.linuxhomenetworking.com/wiki/index.php/Quick_HOWTO_:_Ch18_:_Configuring_DNS

http://linux.die.net/man/5/nscd.conf

分享到:
评论

相关推荐

    Java自带的HttpURLConnection访问接口实现文件上传

    在Java中,我们首先创建HttpURLConnection实例,设置连接属性,例如设置请求方法为POST,设置允许输入和输出流,并启用自动重定向。 ```java URL url = new URL("http://server.com/upload"); HttpURLConnection ...

    JAVA通过HttpURLConnection 上传和下载文件的方法

    JAVA通过HttpURLConnection上传和下载文件的方法 JAVA通过HttpURLConnection上传和下载文件的方法是非常有实用价值的,需要的朋友可以参考下。HttpURLConnection是一个Java类,用于从网络中读取数据或向网络中写入...

    java实现多次HttpURLConnection共享session

    总结来说,Java实现多次HttpURLConnection共享session的关键在于正确处理Cookie,保存服务器返回的Session ID,并在后续请求中携带这个ID。通过这种方式,即使没有浏览器环境,也能模拟登录状态,爬取登录后的内容。...

    HttpURLConnection文件下载\httpURLConnection文件下载

    总的来说,这段代码展示了如何利用`HttpURLConnection`进行文件下载的基本步骤,包括创建连接、设置超时、读取和写入数据。注意,实际应用中可能需要考虑更多的异常处理和错误恢复策略,以及更高效的下载策略,如...

    CUrl类是以命令行工具CUrl为参考使用标准Java的HttpURLConnection实现的Http工具类

    CUrl类是一个基于Java的HttpURLConnection实现的网络通信工具,其设计灵感来源于命令行工具CUrl。CUrl命令行工具广泛用于在各种协议下发送数据,包括HTTP、HTTPS、FTP等,而CUrl类则是将这种功能移植到了Java平台,...

    java后台调用HttpURLConnection类模拟浏览器请求实例(可用于接口调用)

    3. 设置请求属性:你可以设置如`setDoOutput(true)`(对于POST请求)或`setRequestMethod("GET")`等属性,以指定请求类型和行为。 4. 发送请求数据:如果请求类型是POST,可以通过`DataOutputStream`写入请求体的...

    java获取公网IP

    在IT行业中,公网IP(Public IP)是指互联网上唯一标识一台设备的IP地址,与之相对的是私网IP(Private IP),后者在局域网内部使用。公网IP是全球唯一的,使得任何网络上的设备都能通过它进行通信。本文将详细讨论...

    java 动态换ip限制 ip频繁限制

    在提供的文件`crawlercity`中,可能包含了关于如何构建爬虫城市(可能是一个大规模的爬虫项目)的相关代码和配置,包括代理IP的获取、请求调度和异常处理等内容。通过对这些文件的学习和研究,我们可以深入了解如何...

    java HttpURLConnection工具

    java HttpURLConnection示例 HttpURLConnection工具

    Java 实现 客户端 HttpURLConnection

    Java 实现 客户端 HttpURLConnection 用于进行web服务器测试的http客户端

    使用HttpUrlConnection实现上传文件 服务器端代码

    在Java编程环境中,当需要与Web服务器交互,例如上传文件时,`HttpURLConnection`是一个常见的选择,因为它提供了灵活且高效的方式。本篇文章将详细讲解如何使用`HttpURLConnection`实现文件上传,同时涉及到服务器...

    本示例使用HttpUrlConnection实现上传文件

    在本示例中,`ch09_uploadfile`可能是包含具体实现代码的文件夹,可能包括了用于读取本地文件、构造请求头和写入文件内容的Java源代码。配合`my_upload`工程运行,意味着`my_upload`可能是一个服务器端的应用,用于...

    JAVA实现HTTP请求

    这个是我自己集成框架的时候写的一个HTTP请求的辅助类,主要是通过HttpURLConnection 来实现JAVA的HTTP请求,有的人会问、为什么有些网站发请求没问题,有些网站发请求却返回数据,在给网站发送请求的时候,请看清楚...

    HttpURLConnection servlet 多文件参数 断点上传

    在IT行业中,网络编程是不可或缺的一部分,而HTTP协议作为互联网上的通信标准,其在Java中的实现通常是通过`HttpURLConnection`类。本知识点将深入探讨如何使用`HttpURLConnection`与Servlet协同工作,处理多文件...

    Java 中HttpURLConnection附件上传的实例详解

    本文详细介绍了Java 中HttpURLConnection附件上传的实例详解,包括HttpURLConnection简介、附件上传的基本原理、使用HttpURLConnection实现附件上传的示例代码分析、HttpURLConnection附件上传的优点和缺点等。...

    Android-使用HttpURLConnection实现断点续传

    可以通过设置请求头`If-Modified-Since`和`Range`来实现。如果服务器支持断点续传,它会返回文件的总大小。 ```java HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection....

    安卓基于HttpURLConnection的网络访问.java

    基于HttpURLConnection的网络访问 已封装好,一句话访问网络 可采用GET和POST两种方式访问

    基于Socket和HttpURLConnection的爬虫实例

    本实例将重点讲解如何利用Java中的Socket和HttpURLConnection库来实现一个简单的网络爬虫。这两个类是Java标准库提供的基础网络通信工具,对于理解HTTP协议和网络编程具有重要意义。 首先,让我们了解Socket编程。...

    java HttpURLConnection 使用示例

    在本文中,我们将深入探讨`HttpURLConnection`的使用,包括GET和POST请求的实现,以及如何处理可能出现的乱码问题。 一、`HttpURLConnection`概述 `HttpURLConnection`是`URLConnection`的子类,专门用于处理HTTP...

    Java的HttpURLConnection的封装类

    用于对基于HTTP的服务进行抓取 HttpClient 现在是HttpComponents 把问题搞复杂了 其实Java内置的HttpURLConnection很好的 内含文档 使用方法见http: blog csdn net jdgdf566 article details 16357677

Global site tag (gtag.js) - Google Analytics