我正在運行一個多線程的簡約http服務器(不是一個web服務器,但是),它接受三個服務器套接字上的連接:local,internet和internet-ssl。從SSLSocket讀取最快或最好的方法
每個套接字的超時時間爲1000毫秒(可能會在未來降低)。
工作線程讀取請求是這樣的:
byte[] reqBuffer = new byte[512];
theSocket.getInputStream().read(reqBuffer);
現在的問題是,隨着新實施的SSL插槽與1/N-1記錄分裂技術問題就出現了。還有些客戶一分爲其他奇怪的方式使用SSL(4/N-4等)的時候,所以我想我可能只是執行多個讀取這樣的:
byte[] reqBuffer = new byte[512];
InputStream is = theSocket.getInputStream();
int read = is.read(reqBuffer, 0, 128); // inital read - with x/n-x this is very small
int pos = 0;
if (read > 0) {
pos = read;
}
int i = 0;
do {
read = is.read(reqBuffer, pos, 128);
if (read > 0) {
pos += read;
}
i++;
} while(read == 128 && i < 3); // max. 3 more reads (4 total = 512 bytes) or until less than 128 bytes are read (request should be completely read)
與像Firefox或Chrome等瀏覽器的客戶端工作使用該技術。
現在我的問題是,新方法要慢得多。對本地套接字的請求非常慢,以至於超時2秒的腳本超時請求(我不知道爲什麼)。也許我在我的代碼中有一些邏輯問題?
有沒有更好的方法來讀取SSL套接字?因爲每秒鐘有多達數百甚至上千個請求,並且新的讀取方法甚至會降低http請求的速度。
注意:ssl-socket目前沒有使用,直到我可以解決此問題纔會使用。
我也嘗試使用緩衝讀取器讀取行,因爲我們在這裏討論http,但服務器爆炸用盡文件描述符(限制爲20 000)。雖然可能是因爲我的實施。
我很感謝關於這個問題的每一個建議。如果您需要更多關於代碼的信息,請告訴我,我會盡快發佈。
編輯: 我實際上把更多的思想放在了我想要做的事情上,並且我意識到它歸結爲讀取HTTP標頭。所以最好的解決方案是實際讀取行(或字符的字符)的請求行,並停止讀取x行或直到到達空行(標記結尾)。 我目前的做法是將BufferedInputStream放在套接字的InputStream周圍,並用一個由BufferedReader「讀取」的InputStreamReader讀取它(問題:當我使用BufferedReader時使用BufferedInputStream是否合理?)。 此BufferedReader讀取字符的請求字符,檢測行結束符(\ r \ n)並繼續讀取,直到達到長度超過64個字符的行,讀取最多8行或到達空行(標記HTTP標頭的結尾)。我將在明天測試我的實現並相應地編輯此編輯。
編輯: 我幾乎忘了在這裏寫我的結果:它的工作原理。在每個套接字上,甚至比以前的工作方式更快。感謝大家指點我正確的方向。我最終實現這樣的:
List<String> requestLines = new ArrayList<String>(6);
InputStream is = this.cSocket.getInputStream();
bis = new BufferedInputStream(is, 1024);
InputStreamReader isr = new InputStreamReader(bis, Config.REQUEST_ENCODING);
BufferedReader br = new BufferedReader(isr);
/* read input character for character
* maximum line size is 768 characters
* maximum number of lines is 6
* lines are defined as char sequences ending with \r\n
* read lines are added to a list
* reading stops at the first empty line => HTTP header end
*/
int readChar; // the last read character
int characterCount = 0; // the character count in the line that is currently being read
int lineCount = 0; // the overall line count
char[] charBuffer = new char[768]; // create a character buffer with space for 768 characters (max line size)
// read as long as the stream is not closed/EOF, the character count in the current line is below 768 and the number of lines read is below 6
while((readChar = br.read()) != -1 && characterCount < 768 && lineCount < 6) {
charBuffer[characterCount] = (char) readChar; // fill the char buffer with the read character
if (readChar == '\n' && characterCount > 0 && charBuffer[characterCount-1] == '\r') { // if end of line is detected (\r\n)
if (characterCount == 1) { // if empty line
break; // stop reading after an empty line (HTTP header ended)
}
requestLines.add(new String(charBuffer, 0, characterCount-1)); // add the read line to the readLines list (and leave out the \r)
// charBuffer = new char[768]; // clear the buffer - not required
characterCount = 0; // reset character count for next line
lineCount++; // increase read line count
} else {
characterCount++; // if not end of line, increase read character count
}
}
你是什麼意思「* http(s)服務器(不是網絡服務器雖然)*」? – Bruno
@布魯諾那麼它不是向瀏覽器提供網站或類似的東西。它僅實現HTTP協議的一小部分,並執行一些骯髒(但可靠)和快速的請求分析。 – Kazuo
感謝您的建議。閱讀所有這些流和讀者,讓我得出結論,我應該依賴我正在處理的協議。由於我只需要HTTP頭,這應該是一個非常簡單的任務(在處理內容長度頭之後仔細閱讀內容也不會有太大問題)。 我編輯了我原來的帖子以反映這一點。 – Kazuo