为什么使用Java套接字永远无法到达输入流的末尾?
我正在用Java编写一个简单的代理。我无法将给定请求的全部内容读入字节数组。具体地说,在下面的循环中,对“read”的调用会阻塞,即使客户端已经发送了它将要发送的所有数据(也就是说,永远不会到达流的末尾)。因为我不能确定是时候开始写输出了,直到我读了输入的全部内容,这导致了一点麻烦。如果我断开与服务器的连接,最终到达流的末尾,一切都会顺利进行(来自客户端的所有数据,在本例中是请求www.google.com的Firefox,都已被服务器读取,并且它能够根据需要进行处理,尽管显然它无法将任何数据发送回客户端) InputStream直接来自客户端套接字(getInputStream(),然后缓冲);OutputStream是ByteArrayOutputStream为什么使用Java套接字永远无法到达输入流的末尾?,java,sockets,stream,Java,Sockets,Stream,我正在用Java编写一个简单的代理。我无法将给定请求的全部内容读入字节数组。具体地说,在下面的循环中,对“read”的调用会阻塞,即使客户端已经发送了它将要发送的所有数据(也就是说,永远不会到达流的末尾)。因为我不能确定是时候开始写输出了,直到我读了输入的全部内容,这导致了一点麻烦。如果我断开与服务器的连接,最终到达流的末尾,一切都会顺利进行(来自客户端的所有数据,在本例中是请求www.google.com的Firefox,都已被服务器读取,并且它能够根据需要进行处理,尽管显然它无法将任何数据发
我做错了什么?通常在HTTP中,
内容长度
标题指示应该从流中读取多少数据。基本上,它告诉您在指示HTTP头结束的双换行符(实际上是双换行符)后面有多少字节。有关更多信息,请参阅
如果未发送内容长度
标题,您可以尝试在经过一定时间后中断读取,而不通过连接发送数据,尽管这绝对不是首选
(我假设您将以某种方式处理正在读取的数据,否则您可以在读取数据时写出每个字节)HTTP 1.1由所有现代浏览器支持,具有一种称为“保持活动”或“持久连接”的功能,其中,默认情况下允许客户端为多个请求重用到服务器的HTTP 1.1连接(请参阅)。 因此,如果您指向FF,那么到www.google.com:80的连接将保持打开状态一段时间,即使第一个请求已经完成。因此,如果应用程序对HTTP协议没有基本了解,就无法知道是否已发送了所有数据。 您可以通过在连接上使用超时来避免这种情况,希望客户端不会被卡在某个地方,而这种沉默实际上意味着数据块的结束。
另一种方法是重写服务器响应头,将代理发布为符合HTTP 1.0而不是1.1的,从而禁止客户端使用持久连接。请记住,并非所有连接都有
内容长度
头;有些可能是在对内容长度进行编码并将其作为正文的一部分时使用的。完全正确。在套接字级别,除非有一方明确关闭连接,否则流将永远不会结束,因为它可以重复使用(请参阅:connection:Keep Alive);如果要求的第一件事是尺寸,那就太好了。哇,接球不错。我怀疑,你的方法应该适用于除了http连接之外的几乎所有东西。大量的文件/流复制代码与您的代码完全相同。
public static void copyStream(InputStream is, OutputStream os) throws IOException
{
int read = 0;
byte[] buffer = new byte[BUFFER_SIZE];
while((read = is.read(buffer, 0, BUFFER_SIZE)) != -1)
{
os.write(buffer, 0, read);
}
return;
}