使用InputStreamReader和BufferedReader读取HTTP响应缓慢



我有以下Java代码,它向web服务器发送HTTP请求并读取响应:

StringBuilder response = new StringBuilder(50000);
URL url2 = new URL(ServiceURL); 
connection = (HttpURLConnection)url2.openConnection();
connection.setRequestMethod("POST");
//... (some more connection settings) ...
BufferedWriter  wr = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));
wr.write(Request);
wr.flush ();
wr.close ();
InputStream is = connection.getInputStream();       
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
int i = 0;
while ((i = rd.read()) > 0) {
response.append((char)i);
}

它适用于大多数情况,但我遇到了一个问题,即一台服务器返回了一个相当大的XML(大约500KB;我想这对于一堆文本来说是相当大的。),在那里我不断收到读取超时异常。

我相信这不是网络问题,因为我尝试过使用curl发出同样的请求,结果响应很快,大约两秒钟。

当我查看网络中发生了什么(使用wireshark捕获数据包)时,我注意到我电脑中的TCP接收窗口在某个时候会满。TCP堆栈有时会幸存下来;我可以看到服务器发送TCP保持活动以保持连接,但最终TCP连接会中断。

可能是代码的读取部分(逐个字符地附加收到的响应)使我的代码变慢了吗?有没有更有效的方法来读取HTTP响应?

逐字符读取相当慢,是的。尝试一次将块读取到缓冲区中:

char[] buf = new char[2048];
int charsRead;
while((charsRead = rd.read(buf, 0, 2048)) > 0) {
response.append(buf, 0, charsRead);
}

正如Phil已经说过的,逐字节读取流有点慢。我更喜欢使用BufferedReader:的readLine()方法

StringBuilder response = new StringBuilder();
String line = "";
while((line = rd.readLine()) != null) {
response.append(line + System.getProperty("line.separator");
}

如果可能的话,我会考虑使用ApacheHTTPClient库。它很容易使用,并且在处理HTTP内容时非常强大。http://hc.apache.org/httpcomponents-client-ga/

您还应该记住设置套接字和连接超时。通过这种方式,您可以控制连接保持打开的时间(至少在连接的一侧)。

最后但同样重要的是,在收到响应后,总是在finally块中关闭HTTP连接,否则可能会遇到太多打开文件的问题。

希望这能成功;)

最新更新