先看看下面這段代碼(有删節)
public static String send(String sendurl, String sendText) throws Exception {
URL url = null;
URLConnection uc = null;
//建立連接配接、輸出資料等;
String strReceive = "";
try {
InputStream is = uc.getInputStream();
DataInputStream in = new DataInputStream(is);
int blockLen = in.available();
byte block[] = new byte[blockLen];
for (int readLen = -9999; readLen != -1;) {
readLen = in.read(block);
if (readLen != -1)
strReceive = strReceive + new String(block);
}
is.close();
in.close();
} catch (IOException e) {
logger.info("httpl接收錯誤1:" + e.getMessage());
}
return strReceive;
}
注意紅色字型那幾行。blockLen被用來建立一個位元組數組block,block作為資料緩沖來讀取inputstream裡的資料。然後循環 從inputstream中讀取資料,寫入block中。
考慮一種情況。如果網絡阻塞了,inputstream已經打開,但是資料卻還沒有傳輸過來,會發生什麼?
inputstream.available()方法傳回的值是該inputstream在不被阻塞的情況下一次可以讀取到的資料長度。如果資料還 沒有傳輸過來,那麼這個inputstream勢必會被阻塞,進而導緻inputstream.available傳回0。而對 inputstream.read(byte[] b)而言,如果b的長度等于0,該方法将傳回0。
回頭看看這個循環體的結束條件,是readLen == -1時跳出。顯然,上面提到的網絡阻塞情況發生之後,代碼将陷入這個死循環當中。
這是我們在工程應用中遇到的一個問題。由外包商提供的工具jar包中的這段代碼,直接将我們的伺服器 拉進了死循環。
我們的解決方法,是将整個接收與發送的方法進行改寫,使用了下面的這段代碼:
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(prpUrl);
method.setRequestBody(sendstr);
method.getParams().setParameter(
HttpMethodParams.HTTP_CONTENT_CHARSET, "GBK");
client.executeMethod(method);
// rtnXml = method.getResponseBodyAsString();
InputStream txtis = method.getResponseBodyAsStream();
BufferedReader br = new BufferedReader(new InputStreamReader(txtis));
String tempbf;
StringBuffer html = new StringBuffer(100);
while ((tempbf = br.readLine()) != null) {
html.append(tempbf);
}
rtnXml = html.toString();
method.releaseConnection();
确确實實的,解決了問題。
如果仍然要采用原方法中手動打開輸入流、建立緩沖區、循環讀取資料的方法,那麼不應該用 available這個字段來作為緩沖區的初始長度。可以考慮手工設定一個固定值;或者讀取http封包頭的content-length屬性值。最後的 這種方式沒有嘗試過。
本文轉自 斯然在天邊 51CTO部落格,原文連結:http://blog.51cto.com/winters1224/799056,如需轉載請自行聯系原作者