Java Socket InputStream read()总是返回-1,结束之前

问题描述:

我正在写下载程序。我只想用java Socket来请求一个文件。所以我按照HTTP协议规则在我的套接字中编写。我的应用程序创建连接并在读取标题后,使用我的套接字的InputStreamread()方法。一切顺利。有时连接可能会丢失。但是我存储了我正在读取的哪个字节,因此它再次创建一个具有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) 

我不知道是什么问题,但不管是什么,它发生在近流的结束。 我花了很多时间花了很多时间,我完全困惑。我会很感激任何帮助!

感谢名单

+0

Whad有'readHeaders'吗?你确定它没有阅读更多的信息吗?它使用某种缓冲区吗? –

+0

在'readHeaders'中,我从套接字输入流中创建了一个'BufferedReader'并且完全读取到body。如果它不是确切的,它会在控制台中打印一些内容! – MHM

+2

@MHM:那就是你的问题!一个'BufferedReader'将**读入一个缓冲区**,从中可以获取内容。这意味着当'readHeaders'返回时,比标题更多的**将被从'InputStream'中读取。这意味着你缺少的数据是*在开始处*,而不是在末尾。 –

你在你readHeaders()方法上的InputStream上层叠缓冲的阅读器/流?我的猜测是你正在这样做,而且这个缓冲流正在读取比你期望的更多的InputStream(因为它是缓冲的)。这些字节然后从readHeaders()方法返回时丢失。

更新:

刚刚看到您的最新评论。这正是你的问题。 BufferedReader占用了主体字节的一部分。

+0

谢谢队友,你有东西,让我检查一下! – MHM

+1

正确读取头文件是在Java中实现HTTP协议最棘手的部分之一。 –

+1

提示:最好读入一个字节数组并找到'\ r \ n \ r \ n'(CR LF CR LF)序列(和空行),然后将*之前的部分*转换为'字符串“(这是你的标题),以及*之后的所有* *是数据的开头*。 –