Java Socket InputStream read()总是返回-1,结束之前
我正在写下载程序。我只想用java Socket来请求一个文件。所以我按照HTTP协议规则在我的套接字中编写。我的应用程序创建连接并在读取标题后,使用我的套接字的InputStream
的read()
方法。一切顺利。有时连接可能会丢失。但是我存储了我正在读取的哪个字节,因此它再次创建一个具有HTTP远程GET的新Socket并继续其工作。但是,当下载即将完成时,我的意思是当少于10 KB时,所有连接都将丢失,并再次(按计划)尝试打开新的套接字并继续工作。它完全读取响应的标题,但在读取正文的任何字节之前,read()
方法返回-1并再次尝试打开一个新的套接字和read()
其余字节,但问题仍然存在。重点是每次响应标题可以完全读取。并且我看到Content-Length:
响应头字段正好是文件的其余字节。我忘了提及:我的代码有一个问题,因为我检查了很多服务器上的许多文件,结果是一样的。这里是代码:Java Socket InputStream read()总是返回-1,结束之前
// Some fields:
int state;
long start, current, end;
// in a thread:
while (state != FINISHED) {
if (state == DOWNLOADING) {
try {
// fill a new socket with Ranged GET [current, end]
Socket s = initConnection();
InputStream in = s.getInputStream();
int readNo = 0;
FileOutputStream out = getTempFile();
byte[] buffer = new byte[1024];
// read response headers successfully and prints them, request range is OK. a sample of its print is at the end of page
readHeaders(in);
while (state == DOWNLOADING && (readNo = in.read(buffer)) != -1) {
current += readNo;
out.write(buffer, 0, readNo);
}
if (readNo == -1) {
// at nearly end of download always print this and values never changes, where usually they have 3000 byte difference
System.out.println("**************> (" + current + " - " + end + ")");
}
if (currentByte == endByte) {
state = FINISHED;
//mergeParts();
// code never reaches here
dlInfo.checkAllPartsFinished();
}
out.flush();
out.close();
s.close();
} catch (Exception e) {
e.printStackTrace();
state = ERROR;
error = e.getMessage();
errorRetry++;
}
} else if (state == PAUSED) {
// ...
} else ...
}
}
在文件的结尾那里没有什么变化的响应头的一个示例:
HTTP/1.1 206 Partial Content
Date: Mon, 21 May 2012 14:34:27 GMT
Server: Apache
Last-Modified: Sat, 21 Apr 2012 02:16:20 GMT
ETag: "4006d32e-f691e0-4be26fda00500"
Accept-Ranges: bytes
Content-Length: 7859
Content-Range: bytes 2012041-2019899/16159200
Connection: close
Content-Type: application/octet-stream
**************> (2012041 - 2019899)
我不知道是什么问题,但不管是什么,它发生在近流的结束。 我花了很多时间花了很多时间,我完全困惑。我会很感激任何帮助!
感谢名单
你在你readHeaders()
方法上的InputStream上层叠缓冲的阅读器/流?我的猜测是你正在这样做,而且这个缓冲流正在读取比你期望的更多的InputStream(因为它是缓冲的)。这些字节然后从readHeaders()
方法返回时丢失。
更新:
刚刚看到您的最新评论。这正是你的问题。 BufferedReader占用了主体字节的一部分。
谢谢队友,你有东西,让我检查一下! – MHM
正确读取头文件是在Java中实现HTTP协议最棘手的部分之一。 –
提示:最好读入一个字节数组并找到'\ r \ n \ r \ n'(CR LF CR LF)序列(和空行),然后将*之前的部分*转换为'字符串“(这是你的标题),以及*之后的所有* *是数据的开头*。 –
Whad有'readHeaders'吗?你确定它没有阅读更多的信息吗?它使用某种缓冲区吗? –
在'readHeaders'中,我从套接字输入流中创建了一个'BufferedReader'并且完全读取到body。如果它不是确切的,它会在控制台中打印一些内容! – MHM
@MHM:那就是你的问题!一个'BufferedReader'将**读入一个缓冲区**,从中可以获取内容。这意味着当'readHeaders'返回时,比标题更多的**将被从'InputStream'中读取。这意味着你缺少的数据是*在开始处*,而不是在末尾。 –