BufferedReader 卡在 readLine() 中
BufferedReader stuck in readLine()
我正在尝试从 Google Chrome 获取 HTTP 请求以获取它的数据。为此,我使用 BufferedReader
中的 readLine()
但出于某种原因,我认为它卡在了最后一行,因为缓冲区保持打开状态并且它一直在等待更多输入。这是我在 while 循环中使用的代码:
String line;
ArrayList<String> request = new ArrayList<String>();
while ((line = inFromClient.readLine()) != null) {
request.add(line);
}
如果我强行打破它工作的循环,基本上我试图有效地读取所有行但没有 ready()
的不一致
HTTP 似乎是一个疯狂的简单协议,但事实并非如此;您应该使用 HTTP 客户端库,例如 built-in java.net.http
客户端。
问题是 'give me my data, then close it down' 的概念是 HTTP/1.0,这已经过时了几十年。 HTTP/2.0 和 HTTP/3.0 是二进制协议,而 HTTP/1.1 倾向于保持连接打开。一般来说,'read lines',甚至 'use Reader'(例如,读取字符而不是字节) 是错误的处理方式,因为 HTTP 不是文本协议。我知道。它看起来像一个。不是。
这里是一个高度简化的概述,例如如何。浏览器读取 HTTP/1.1 响应:
- 使用原始字节处理,因为 HTTP body 内容是原始的(或可能是),因此将整个内容包装成例如
InputStreamReader
或 BufferedReader
是 non-starter.
- 继续阅读,直到一个 0x0A 字节(在 ASCII 中,换行符),或 X 字节已被读取并且您的缓冲区已满,其中 X 不是特别大.不希望性能不佳的服务器或连接到不同 (non-HTTP) 服务的误解导致内存问题!将第一行解析为 HTTP/1.1 响应。
- 继续执行此循环以拾取所有 header。使用相同的 'my buffer has limits' 技巧来避免内存问题。
- 然后检查响应代码以确定是否会收到 body。它是 HTTP/1.1,所以你不能直接说:“好吧,如果连接关闭,我想不会有 body”。来不来主要看响应码
- 假设 body 存在,读取将 header 与 body 分开的 double-newline。
- 如果内容作为分块编码(常见)传输,开始将数据 blitting 到缓冲区,但检查是否读取了整个块。阅读分块编码是它自己的游戏,真的。
- 或者,HTTP/1.1 要求 如果不使用分块编码,则
Content-Length
存在。使用此 header 可准确了解要读取的字节数。
- 'a newline' 和 'close connection' 都不能作为 HTTP/1.1 中 'end of data' 的有意义的标记,所以,不要。
- 然后要么将content+headers+returncode逐字传递给请求代码,要么修饰一下。例如,如果
Content-Type
header 存在并且值为 text/html; encoding=UTF-8
您可以考虑获取 body 数据并通过 UTF-8 (new String(byteArray, StandardCharsets.UTF_8);
).
请注意,我已经忽略了服务器所做的一些奇怪的行为,因为在过去,一些愚蠢的浏览器做了奇怪的事情,现在是现状(例如,范围请求非常奇怪)当然还有HTTP2和HTTP3是完全不同的协议。
此外,当然,如今 HTTP 服务器很少见; HTTPS 就是它的用武之地,这也很不一样。
我正在尝试从 Google Chrome 获取 HTTP 请求以获取它的数据。为此,我使用 BufferedReader
中的 readLine()
但出于某种原因,我认为它卡在了最后一行,因为缓冲区保持打开状态并且它一直在等待更多输入。这是我在 while 循环中使用的代码:
String line;
ArrayList<String> request = new ArrayList<String>();
while ((line = inFromClient.readLine()) != null) {
request.add(line);
}
如果我强行打破它工作的循环,基本上我试图有效地读取所有行但没有 ready()
HTTP 似乎是一个疯狂的简单协议,但事实并非如此;您应该使用 HTTP 客户端库,例如 built-in java.net.http
客户端。
问题是 'give me my data, then close it down' 的概念是 HTTP/1.0,这已经过时了几十年。 HTTP/2.0 和 HTTP/3.0 是二进制协议,而 HTTP/1.1 倾向于保持连接打开。一般来说,'read lines',甚至 'use Reader'(例如,读取字符而不是字节) 是错误的处理方式,因为 HTTP 不是文本协议。我知道。它看起来像一个。不是。
这里是一个高度简化的概述,例如如何。浏览器读取 HTTP/1.1 响应:
- 使用原始字节处理,因为 HTTP body 内容是原始的(或可能是),因此将整个内容包装成例如
InputStreamReader
或BufferedReader
是 non-starter. - 继续阅读,直到一个 0x0A 字节(在 ASCII 中,换行符),或 X 字节已被读取并且您的缓冲区已满,其中 X 不是特别大.不希望性能不佳的服务器或连接到不同 (non-HTTP) 服务的误解导致内存问题!将第一行解析为 HTTP/1.1 响应。
- 继续执行此循环以拾取所有 header。使用相同的 'my buffer has limits' 技巧来避免内存问题。
- 然后检查响应代码以确定是否会收到 body。它是 HTTP/1.1,所以你不能直接说:“好吧,如果连接关闭,我想不会有 body”。来不来主要看响应码
- 假设 body 存在,读取将 header 与 body 分开的 double-newline。
- 如果内容作为分块编码(常见)传输,开始将数据 blitting 到缓冲区,但检查是否读取了整个块。阅读分块编码是它自己的游戏,真的。
- 或者,HTTP/1.1 要求 如果不使用分块编码,则
Content-Length
存在。使用此 header 可准确了解要读取的字节数。 - 'a newline' 和 'close connection' 都不能作为 HTTP/1.1 中 'end of data' 的有意义的标记,所以,不要。
- 然后要么将content+headers+returncode逐字传递给请求代码,要么修饰一下。例如,如果
Content-Type
header 存在并且值为text/html; encoding=UTF-8
您可以考虑获取 body 数据并通过 UTF-8 (new String(byteArray, StandardCharsets.UTF_8);
).
请注意,我已经忽略了服务器所做的一些奇怪的行为,因为在过去,一些愚蠢的浏览器做了奇怪的事情,现在是现状(例如,范围请求非常奇怪)当然还有HTTP2和HTTP3是完全不同的协议。
此外,当然,如今 HTTP 服务器很少见; HTTPS 就是它的用武之地,这也很不一样。