我正在运行一个多线程简约 http(s) 服务器(虽然不是 Web 服务器),它接受三个服务器套接字上的连接:本地、互联网和 internet-ssl。
每个套接字的超时时间为 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 行之后停止读取,或者直到达到空行(标记标题的结尾)。我目前的方法是在套接字的 InputStream 周围放置一个 BufferedInputStream 并使用 InputStreamReader 读取它,该 InputStreamReader 由 BufferedReader“读取”(问题:当我使用 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
}
}