我想了解在Java中使用HttpURLConnection類(或HttpsURLConnection類)執行HTTP請求的邏輯。下面是我的代碼,執行一個GET請求,并將所有回應的有效載荷列印到stdout.
URL url = new URI("https: //swapi. dev/api/planets/1/")。)
字串行。
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection() 。
connection.setRequestMethod("GET")。
connection.setRequestProperty("Accept", "application/json") 。
BufferedReader input = new BufferedReader(
new InputStreamReader(connection.getInputStream()
);
//從回應的有效載荷中讀取所有資料& 列印到螢屏上。
while ((line=input.readLine()) != null) {
System.out.println(line)。
}
System.out.println("All data retrieved!") 。
問題來了:這段代碼作業得很好,成功地讀取了所有的資訊,并完成了運行!我的問題是,為什么會出現這種情況?我的問題是,為什么執行最終沒有在 while 回圈中的 input.readLine() 部分被阻止?
當我在 TCP 級別上做類似的 while 回圈讀取時,這樣的 readLine 將被阻塞,直到客戶端關閉連接。根據HttpURLConnection類的檔案(here),由于性能原因,底層的TCP連接通常不會被關閉。因此,如果我把connection.getInputStream()想象成與TCP模擬中的socket.getInputStream()相同,我希望input.readLine()的呼叫最終也會被阻止。
我猜想這個方法可能在HttpURLConnection的某個地方被多載(也許是為了利用Content-Length頭的屬性?) 然而,我在任何地方都找不到這個重寫。
因為我想盡可能地深入研究,如果你能幫助定位HttpURLConnection類如何導致我的while-loop最終結束,那就太好了。
uj5u.com熱心網友回復:
為什么執行最終沒有在while回圈中的
input.readLine()部分被阻止呢?
因為 Reader.readLine() 呼叫在到達它所讀取的輸入流的流尾時將回傳 null。
當服務器端完成了回應資料的發送......并且客戶端已經全部讀完時,它將到達客戶端的流的末端。
流的結束實際上可能與服務器關閉 TCP/IP 連接相對應,也可能與之無關。 如果HTTPchunked transfer encoding被用于HTTP連接,則不會如此。 分塊編碼是在客戶端和服務器同意使用一個連接來處理多個請求/回應時使用的。 分塊頭資訊將告訴客戶端它何時到達檔案的末尾......并且它應該在輸入流上發出結束信號。
content-length頭可能會或可能不會涉及到這個問題1。 但是請記住,服務器可以在沒有content-length頭的情況下發送一個回應......這意味著客戶端將無法提前知道需要多少資料,并且將無法使用它來 "構建 "回應體。
關于更多的細節,請參考指定HTTP的RFCs。 (這比看客戶端的 Java 源代碼要好。 客戶端代碼只能告訴你故事的一半。)
1 - HTTP規范說,如果服務器在回應頭中包括一個
標籤:content-length,它必須準確地發送這個位元組數。 然而,如果服務器發送的位元組數比它說的少或多,它并沒有規定任何具體的客戶端行為。
