2

我在 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(大约 500 KB;我想这对于一堆文本来说相当大..),我不断收到读取超时异常。

我相信这不是网络问题,因为我尝试使用 curl 发出相同的请求,并且响应很快就到达了,大约两秒钟。

当我查看网络中发生的情况(使用wireshark 捕获数据包)时,我注意到我计算机中的TCP 接收窗口有时会满。TCP 堆栈有时会幸免于难;我可以看到服务器发送 TCP keep-alive 以保持连接,但最后 TCP 连接只是中断了。

可能是代码的阅读部分(逐个字符附加收到的响应)正在减慢我的代码速度吗?有没有更有效的方法来读取 HTTP 响应?

4

2 回答 2

1

一个字一个字的读起来很慢,是的。尝试一次将块读入缓冲区:

char[] buf = new char[2048];
int charsRead;
while((charsRead = rd.read(buf, 0, 2048)) > 0) {
    response.append(buf, 0, charsRead);
}
于 2012-11-23T19:02:14.913 回答
0

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

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

如果可能,我会考虑使用 Apache HTTP 客户端库。它易于使用并且在处理 HTTP 内容方面非常强大。 http://hc.apache.org/httpcomponents-client-ga/

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

最后但并非最不重要的一点是,在您收到响应后始终在 finally 块中关闭您的 HTTP 连接,否则您可能会遇到打开文件过多的问题。

希望这个问题 ;)

于 2012-11-23T19:34:12.813 回答