HttpURLConnection.getInputStream非常慢

7

与 iPhone 应用程序使用相同的服务器端服务相比,HttpURLConnection.getInputStream 占用了很多时间。

以下代码用于该服务:

         date= new java.util.Date();             
         Log.d("time","Time Stamp before posting  "+new Timestamp(date.getTime()));

         URL ur= new URL(url);           
         HttpURLConnection conn = (HttpURLConnection) ur.openConnection();
         conn.setRequestProperty("Connection", "close");
         conn.setReadTimeout(10000);
         conn.setConnectTimeout(15000);
         conn.setRequestMethod("POST");
         conn.setDoInput(true);
         conn.setDoOutput(true);             
         OutputStream os = conn.getOutputStream();
         BufferedWriter writer = new BufferedWriter(
                 new OutputStreamWriter(os, "UTF-8"));
         writer.write(getQuery(nameValuePairs));
         writer.close();
         os.close();
         conn.connect();

         StringBuffer response=null;             
         try{           
             Log.d("time","Time Stamp bfr InputStream  "+new Timestamp(date.getTime()));    

             InputStream is = conn.getInputStream();

             date= new java.util.Date();             
             Log.d("time","Time Stamp aftr InputStream  "+new Timestamp(date.getTime()));            

             BufferedReader rd = new BufferedReader(new InputStreamReader(is));
             String line;
             response = new StringBuffer(); 
             while((line = rd.readLine()) != null) {
                 response.append(line);
                 response.append('\r');
             }
             rd.close();
             response.toString();
             result=response.toString();

         } catch (Exception e) {

        }

为了检查服务使用时间,我打印了时间戳的日志条目。

整个过程的平均时间如下:

发布到服务器的平均时间少于2毫秒
创建输入流的平均时间几乎需要5秒钟

写响应的平均时间少于2毫秒。

是否有关于输入流为何花费更多时间导致整个服务变得非常缓慢的想法?

3个回答

1
您所测量的并不是您认为的内容。在调用getInputStream()或getResponseCode()之前,没有任何内容被写入服务器。因此,您实际上正在测量以下内容:
- 连接时间 - 传输时间 - 服务器端处理时间
当您认为自己只是在测量getInputStream()时间时。
原因是HttpURLConnection通过缓冲所有输出来自动设置内容长度标头。您可以通过使用分块传输模式来避免这种情况。然后,至少您将看到时间真正花在哪里。

3
我们该如何做到这一点? - georgiaboy82

0

这可能与JDK 7中引入的一个错误有关。"HttpServer在使用keep-alive缓存时会引入1000毫秒的延迟"。请参见:

http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8009548

根据您的目的,建议的解决方法是将HttpUrlConnection多线程化。例如,如果您正在使用HttpServer,则可以执行以下操作:
server.setExecutor( Executors.newFixedThreadPool( 5 ) );

1
只有在对方使用HttpServer时才会出现这种情况。没有证据表明如此。建议的解决方法是多线程服务器,但这与问题无关。 - user207421

0

将urlConnection.setConnectTimeout()设置为较低的超时时间。

URLConnection.setConnectTimeout()的类文档说:

设置连接时等待的最长时间(以毫秒为单位)。如果在建立连接之前超时时间到期,则连接服务器将失败并引发SocketTimeoutException。默认值为0会导致我们进行阻塞连接。这并不意味着我们永远不会超时,但这可能意味着您将在几分钟后获得TCP超时。

警告:如果主机名解析为多个IP地址,则此客户端将按照RFC 3484顺序尝试每个IP地址。如果连接到这些地址中的每个地址都失败,则在连接尝试抛出异常之前将经过多个超时时间。同时支持IPv6和IPv4的主机名始终至少有2个IP地址。

我最初将其设置为urlConnection.setConnectTimeout(30000);,然后将其更改为urlConnection.setConnectTimeout(1000)。立即看到了更快的结果。

希望这可以帮助你!


4
你的意思是在出现连接失败时更快地发现了它们(如果有的话)。很难看出这如何解决原帖作者的问题。 - user207421
很奇怪,但它有效!也许while循环一直在循环或者其他什么问题,但对我来说,这个答案完美地解决了我的问题! - WR-BikAir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接