作为一项挑战,我用 Java 实现了一个基本的 Web 服务器。当我打开原始 InputStream
时,我立即进入阻塞读取,将 HTTP 请求的整个 400 字节或字节读取到字节数组中。这行得通,但是我不再检查任何数据,而是在发送响应后简单地关闭套接字。
我想知道是否有更可靠的方法来执行此操作,以免遗漏来自客户端的任何数据。我想一次读取一个字节,直到 read
返回流的结尾。然而,它有时会在没有更多数据时阻塞,并且令人困惑的是 public abtract int InputStream.read()
的 JavaDocs 说:
如果因为已到达流的末尾而没有可用字节,则返回值 -1。此方法会阻塞,直到输入数据可用、检测到流结束或引发异常。
所以这意味着如果到达流的末尾可能会发生两件事:返回 -1 和阻塞。我看到阻塞了。
我的问题是,对于像 HTTP 这样的协议(protocol),您应该如何从套接字中读取以及您如何知道什么时候您将在此连接中获得所有数据?
最佳答案
您引用的 JavaDoc 不暗示如果到达流的末尾可能会发生两件事。它没有说 当 检测到流结束时读取 block ,而是说直到 检测到流结束。一旦检测到,返回-1。
这解释了您观察到的行为:未检测到流的结尾并且读取被阻止。一旦连接关闭,就会检测到流的结尾,但它不会关闭,因为客户端在发送请求后不会立即关闭连接。它必须保持打开状态才能收到回复。
为了确保您从客户端接收到所有数据,您应该解析他们的 HTTP 请求,直到您看到 header 的结尾(双换行符)加上他们在 header 中指定的任何数据量(如果有的话)。
如果您想避免阻塞,请查看 java.nio
和 channels (特别是 SocketChannel
)。
关于java - 从 HTTP 服务器中的套接字读取的推荐方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9542623/