【问题标题】:How do I recognize EOF in Java Sockets?如何识别 Java 套接字中的 EOF?
【发布时间】:2011-11-27 19:44:52
【问题描述】:

我想在 Java 套接字中识别 数据流结束。当我运行下面的代码时,它只是卡住并继续运行(它卡在值10)。

我也想让程序下载二进制文件,但是最后一个字节总是不同的,所以我不知道如何停止while(务实)。

String host = "example.com";
String path = "/";
Socket connection = new Socket(host, 80);

PrintWriter out = new PrintWriter(connection.getOutputStream());
  out.write("GET "+ path +" HTTP/1.1\r\nHost: "+ host +"\r\n\r\n");
out.flush();

int dataBuffer;
while ((dataBuffer = connection.getInputStream().read()) != -1)
  System.out.println(dataBuffer);

out.close();

感谢任何提示。

【问题讨论】:

  • 也许我在这里错了,但这应该会发生,因为服务器没有关闭连接。 HTTP 1.1 默认为keep-alive
  • 您不使用现有的 HTTP 库的任何具体原因?
  • 并用请求中的连接头来修复这个问题;)
  • 该程序应该是一个小代理(不仅适用于 HTTP)。
  • @user961912,常用网址可以java.net.URL

标签: java http sockets eof


【解决方案1】:

实际上您的代码正确。

在 HTTP 1.0 中,每个连接都会关闭,因此客户端可以检测到输入何时结束。

在具有持久连接的 HTTP 1.1 中,底层 TCP 连接保持打开状态,因此客户端可以检测输入何时以以下 2 种方式之一结束:

1) HTTP 服务器放置一个Content-Length 标头指示响应的大小。客户端可以使用它来了解何时已完全阅读响应。

2) 响应以Chunked-Encoding 发送,这意味着它以块的形式出现,并以每个块的大小为前缀。使用此信息的客户端可以从服务器接收到的块中构造响应。

您应该使用 HTTP 客户端库,因为实现通用 HTTP 客户端并非易事(我可以这么说)。

要具体说明您发布的代码,您应该遵循上述方法之一。

此外,您应该逐行阅读,因为 HTTP 是行终止协议。

即类似:

BufferedReader in =new BufferedReader(new InputStreamReader( Connection.getInputStream() ) );
String s=null;
while ( (s=in.readLine()) != null)  {
//Read HTTP header
     if (s.isEmpty()) break;//No more headers
   }
}

按照 khachik 的建议发送Connection: close,可以完成工作(因为连接的关闭有助于检测输入的结束)但性能会变差,因为对于每个请求,您都会启动一个新连接。

这当然取决于你想要做什么(如果你在乎)

【讨论】:

  • 标头以空行结束。阅读直到 readLine() 返回 null 与他一开始的问题完全相同。他应该一直读到 s.length() 为零。
  • @EJP:在你投反对票之前,你应该仔细阅读答案。我说他必须使用 HTTP 标头来查找内容长度。代码示例是为了强调他可以逐行解析HTTP
  • @user384706 (a) 你没有任何证据表明谁对帖子投了反对票; (b) 我仔细阅读了你的帖子,发现了一个缺陷并提供了更正。
  • @EJP:好的,关于你是对的反对票。也许我认为你这样做是不公平的。关于这个缺陷,我不同意
  • 那你就错了。你不知道自己的代码是如何工作的。
【解决方案2】:
  1. 您应该使用现有的 HTTP 库。见here
  2. 您的代码按预期工作。服务器不会关闭连接,dataBuffer 永远不会变成-1。发生这种情况是因为默认情况下 HTTP 1.1 中的连接保持活动状态。使用 HTTP 1.0,或将 Connection: close 标头放入您的请求中。

例如:

out.write("GET "+ path +" HTTP/1.1\r\nHost: "+ host +"\r\nConnection: close\r\n\r\n");
out.flush();

int dataBuffer;
while ((dataBuffer = connection.getInputStream().read()) != -1) 
   System.out.print((char)dataBuffer);

out.close();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-21
    • 2018-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    相关资源
    最近更新 更多