Java中套接字、缓冲读取器(BufferedReader)和readline卡在了某个地方... :(

6

我完全不是一名Java程序员。实际上,我尽量避免使用它,但是在课堂上必须使用它(从学校的角度来看)。老师要求我们使用Socket()、BufferedReader()、PrintWriter()和其他各种东西,包括BufferedReader()的readLine()方法。

基本上,我遇到的问题是这样的。文档明确说明readLine应该在输入流的末尾返回null,但实际情况并非如此。

Socket link       = new Socket(this.address, 80);
BufferedReader in = new BufferedReader( new InputStreamReader( link.getInputStream() ));
PrintWriter   out = new PrintWriter(    new PrintWriter(       link.getOutputStream(), true ));

out.print("GET blah blah blah"); // http request by hand
out.flush(); // send the get please

while( (s=in.readLine()) != null ) {

    // prints the html correctly, hooray!!
    System.out.println(s);
}

我不是在HTML的末尾结束,而是得到了一个空行、一个0和另一个空行,然后下一个in.readLine()就永远挂起了。为什么?我的null在哪里?

我尝试使用out.close()来查看是否可能是Yahoo!正在执行持续的http会话或其他操作(我认为如果没有我们愿意执行的头文件,它不会这样做)。

我在网上找到的所有Java套接字示例都表明while循环是正确的形式。我只是不了解足够的Java来调试这个问题。

3个回答

10
你的问题是内容编码为“分块”(chunked)。当从Web服务器请求的内容长度在响应开始时未知时使用此编码。它基本上由正在发送的字节数,后跟 CRLF ,然后是字节组成。你看到的精确序列标志着响应的结束。Web服务器现在正在等待你的下一个请求(这也称为“请求管道化”)。
你有几种可能性:
  • 使用HTTP版本1.0。这将使Web服务器在完全发送响应时自动关闭连接。
  • 在发送请求时指定“Connection:close”标头。这也会关闭连接。
  • 正确解析内容编码“分块”,并简单地将其视为响应现已完成,因为它已经完成了。

这有意义。我需要检查头文件。我将只使用http1.0。 - jettero
是的,对于一个学校练习来说,这是最明智的选择。 - Bombe

7

所以你正在从一个套接字读取(你的代码中没有展示,但我从文本中了解到这一点)?

只要对面没有关闭连接,Java 就不知道它是否在输入的末尾,因此 readLine() 会等待对方发送更多数据,而不返回 null


从套接字读取,是的。我已经将其添加到问题中,谢谢。 - jettero

0

你的HTTP请求没有包含2个回车换行对。发送请求后,你可能还应该调用close方法:

out.print("GET /index.html HTTP/1.0\r\n");
// maybe print optional headers here
// empty line
out.print("\r\n");
out.flush();
out.close();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接