Java 获取分块的HTTPS响应不起作用
我已经被这个问题困扰了很长时间了。关于这一点,我在谷歌上搜索过,还看到了SO中与“chunked”相关的所有链接。所以,最后决定发布这个问题。让我简单介绍一下这个问题。我有一个Java代码,它使用套接字从HTTPS读取响应。响应被正确接收,一切正常,除非传输编码被“分块”。我试图将套接字中的分块响应作为字节数组读取,当我将其转换为字符串时,响应无法读取。我怀疑我在处理区块数据时做错了什么。由于这个问题,当我尝试解压缩响应时,我也得到了“不在GZip格式”异常。我用来处理块的代码是Java 获取分块的HTTPS响应不起作用,java,sockets,chunked-encoding,Java,Sockets,Chunked Encoding,我已经被这个问题困扰了很长时间了。关于这一点,我在谷歌上搜索过,还看到了SO中与“chunked”相关的所有链接。所以,最后决定发布这个问题。让我简单介绍一下这个问题。我有一个Java代码,它使用套接字从HTTPS读取响应。响应被正确接收,一切正常,除非传输编码被“分块”。我试图将套接字中的分块响应作为字节数组读取,当我将其转换为字符串时,响应无法读取。我怀疑我在处理区块数据时做错了什么。由于这个问题,当我尝试解压缩响应时,我也得到了“不在GZip格式”异常。我用来处理块的代码是 int
int chunkLength;
do {
String lengthLine = inStream.readLine();
if (lengthLine == null) {
return false;
}
chunkLength = Integer.parseInt(lengthLine.trim(), 16);
if (chunkLength > 0) {
byte[] chunk = new byte[chunkLength];
int bytesRead = inStream.read(chunk);
if (bytesRead < chunkLength) {
return false;
}
//Burn a CR/LF
inStream.readLine();
}//if chunkLength
} while (chunkLength > 0) ;
return true;
int-chunkLength;
做{
String lengthLine=inStream.readLine();
if(lengthLine==null){
返回false;
}
chunkLength=Integer.parseInt(lengthLine.trim(),16);
如果(chunkLength>0){
byte[]chunk=新字节[chunkLength];
int bytesRead=inStream.read(块);
if(字节读取<块长度){
返回false;
}
//燃烧一个CR/LF
inStream.readLine();
}//如果块长度
}而(chunkLength>0);
返回true;
因为我是新来提问的,所以我可能遗漏了一些(可能很多)细节,这些细节可能是你们给出解决方案所需要的。请原谅我在这种情况下,让我知道,如果你需要更多的细节。任何帮助都将不胜感激。干杯。我在这段代码中看到了三个问题:
Integer.parseInt()
调用,它将失败inStreeam.read()
,因此它可能返回的字节数少于请求的字节数。如果发生这种情况,不要停止读取,这是套接字的正常行为。您需要在循环中调用read()
,直到完整接收到chunkLength
字节数。只有在报告实际错误时才停止读取try {
String line;
do {
// read the chunk header
line = inStream.readLine();
if (line == null) {
return false;
}
// ignore any extensions after the chunk size
int idx = line.indexOf(';');
if (idx != -1) {
line = line.substring(0, idx);
}
// parse the chunk size
int chunkLength = Integer.parseInt(line, 16);
if (chunkLength < 0) {
return false;
}
// has the last chunk been reached?
if (chunkLength == 0) {
break;
}
// read the chunk data
byte[] chunk = new byte[chunkLength];
int offset = 0;
do {
int bytesRead = inStream.read(chunk, offset, chunkLength-offset);
if (bytesRead < 0) {
return false;
}
offset += bytesRead;
} while (offset < chunkLength);
// burn a CRLF at the end of the chunk
inStream.readLine();
// now do something with the chunk...
} while (true);
// read trailing HTTP headers
do {
line = inStream.readLine();
if (line == null) {
return false;
}
// has the last header been read?
if (line.isEmpty()) {
break;
}
// process the line as needed...
} while (true);
// all done
return true;
}
catch (Exception e) {
return false;
}
试试看{
弦线;
做{
//读取块头
line=inStream.readLine();
如果(行==null){
返回false;
}
//忽略块大小之后的任何扩展
int idx=line.indexOf(“;”);
如果(idx!=-1){
line=line.子字符串(0,idx);
}
//解析块大小
int chunkLength=Integer.parseInt(第16行);
if(chunkLength<0){
返回false;
}
//到达最后一块了吗?
如果(chunkLength==0){
打破
}
//读取区块数据
byte[]chunk=新字节[chunkLength];
整数偏移=0;
做{
int bytesRead=inStream.read(chunk,offset,chunkLength offset);
如果(字节读取<0){
返回false;
}
偏移量+=字节读取;
}而(偏移量<长度);
//在块的末尾烧掉一个CRLF
inStream.readLine();
//现在对区块做点什么。。。
}虽然(正确);
//读取尾部HTTP头
做{
line=inStream.readLine();
如果(行==null){
返回false;
}
//是否已读取最后一个标题?
if(line.isEmpty()){
打破
}
//根据需要处理生产线。。。
}虽然(正确);
//全部完成
返回true;
}
捕获(例外e){
返回false;
}
话虽如此,请记住,分块并不能否定TCP/HTTP允许流式传输字节的事实。每个
块
只是较大数据的一小段。因此,不要试图将每个块按原样转换为字符串,或者尝试将其作为一个完整单元进行解压缩。您需要将块
s收集到您选择的文件/容器中,然后在到达HTTP响应末尾后,将整个收集的数据作为一个整体进行处理。除非将数据块推入流处理器,例如支持推式流的GZip解压器。如果确实需要将收集的数据转换为字符串,请确保使用HTTP响应的内容类型
标题中指定的字符集
(如果未指定字符集
,则使用适当的默认值)因此,收集的数据被正确解码为Java的本机UTF-16字符串编码。为什么?为什么不使用HttpURLConnection
呢?谢谢您的及时回复。我们应该使用套接字,这是产品中的一个限制。实际上,我们正在浏览器中设置代理来记录HTTP流量,并使用套接字读取记录的流量。HttpURLConnection
使用套接字。如果有人正在设置一个约束来确定您使用的类,那么它们不应该是。