我正在用 Java 撰寫一個檔案傳輸協議服務器,它使用RFC2616中概述的 HTTP/1.1 標準。
服務器接受連接后,我嘗試提取 HTTP 請求訊息。我想這樣做,我不假設整個訊息將通過單個發送操作發送。我覺得可靠地做到這一點的唯一方法是跟蹤有多少位元組可供讀取,但我在套接字 API 中看不到任何使我能夠做到這一點的東西。
uj5u.com熱心網友回復:
讀取 HTTP/1.1 請求是一個兩步操作:
- 讀取標題欄位
- 使用通過讀取標題欄位獲得的資訊來讀取正文
請求的格式包含在RFC 9112, 2.1 Message format 中:
HTTP-message = start-line CRLF
*( field-line CRLF )
CRLF
[ message-body ]
start-line指包含方法、url 和協議版本的行,然后是 CRLF ( \r\n),然后是 optional field-lines。當您連續閱讀兩個CRLF.
閱讀標題,您將知道正文是否存在,以及它是如何構建的(即如何閱讀它)。有三種可能:
- 標
content-length:頭欄位告訴您在最后一個之后要讀取多少位元組CRLF - 標
transfer-encoding:頭欄位告訴您正文是如何編碼的,以及使用哪種方法來讀取它。實踐中使用的一種方法是chunked。有關該格式的描述,請參見RFC 9112 的第 7.1 節。 - 兩個標頭欄位都不存在,這意味著沒有與請求關聯的正文(請注意,這僅適用于請求,回應不同 - 請參閱第 6 節了解更多詳細資訊)
最后,您會注意到我使用的是 RFC 9112,而不是 RFC 2616。那是因為 9112 是已經過時 2616 的一系列 RFC 的一部分。有關更多詳細資訊,請參閱這篇博客文章和這篇文章。
uj5u.com熱心網友回復:
一個套接字不知道有多少位元組可用,但 RFC2616 提供了一個解決方案。正如您在第 8.1.2.1 節中所讀到的:
為了保持持久性,連接上的所有訊息必須具有自定義的訊息長度(即,不是由連接關閉定義的長度),如第 4.4 節所述。
uj5u.com熱心網友回復:
你能確定一個接受的 Java 套接字中有多少位元組嗎?
簡短的回答是否定的。Socket API 中沒有任何內容可以告訴您整個流的長度。
為什么?因為如果您查看 TCP 協議(??作為流傳輸協議的典型示例),則在傳輸流長度的協議中沒有任何內容......在開始時。實際上,您只知道當(以及是否)接收端收到 FIN 訊息時 TCP 流的長度。(有關更多詳細資訊,請參閱 TCP 規范或Wikipedia。)
這意味著如果您需要知道將在開始時發送的(檔案)位元組數,則需要在應用程式協議層處理此問題。
如果您使用 HTTP/1.x,您將需要處理 Fredrik 在其回答中描述的 3 個變體。請注意,在第三個中,您根本無法提前獲得尺寸。(當然,如果你控制服務器端,你可以確保不會發生......)
注意:如果您嘗試直接在套接字 API 級別實作這一點,那么您有責任閱讀、(正確)理解和(正確)實作您需要的 HTTP/1.x 子集。有些規范相當復雜。并且隨著瀏覽器、服務器、內容交付網路等越來越多地使用新版本的 HTTP,它可能會變得更加復雜。
所以我的建議是:不要這樣做! 在客戶端和服務器端使用現有的 HTTP 協議實作。您將為自己節省大量時間和(大部分)無效的努力。
如果你改變了使用 HTTP 的想法,你基本上可以做你想做的事。但是為了實作在傳輸開始時獲取檔案大小的目標,發送方需要將其作為自定義應用程式協議的一部分發送。
非解決方案:
一旦你InputStream從 a得到一個,Socket你會看到一個available()告訴你可以讀取多少位元組而不阻塞。這不會告訴你整個流的長度。實際上,它甚至不一定是可用位元組數的準確度量。最好忽略它并使用(恒定)固定大小的緩沖區進行讀取。套接字InputStream.read(byte[], ...)呼叫將回傳當前可用的任何位元組(直到緩沖區大小)。僅當當前可用的位元組為零時才會阻塞......并且流尚未關閉。
(該available()方法幾乎沒用。大多數有效的用例可以通過其他方式更好地處理;例如,使用Selector.)
uj5u.com熱心網友回復:
創建 java.net 套接字或 URLConnection 類時,您必須在完成設定后從其方法之一獲取流類。 然后您獲得流類,您可以使用流類中的方法 available() 。注意:java.io 的一個或兩個流類沒有該方法,但可以轉換為具有 available() 的輸出流的輸入流,如果您需要來自流的 wait() ,您還需要包裝一個中斷例外。有關計算 http 資料包和標頭和幀的資訊,請參閱https://docs.oracle.com/javase/7/docs/api/java/net/DatagramSocket.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/512295.html
上一篇:隨后的有序HTTP呼叫
