如何使用BufferedInputStream从Socket中检测输入流的结束?

时间:2016-09-13 01:36:17

标签: java sockets

我正在尝试从Java中的Socket读取和输入,然后通过调用函数来处理它。我必须按字节而不是文本阅读,因为作为文本阅读会因为来自客户端的请求而产生一些错误。所以我决定使用班级BufferedInputStream。问题是没有检测到请求的结束。我想这是因为流不会因为被绞死或其他事而结束......

根据documentationread()函数返回从流中读取的字节,如果流已结束则返回-1。所以,我的代码逐字节读取,将它连接成一个字符串,然后,当流结束时,发送要被处理的字符串(或者至少,应该这样做)。这是代码:

BufferedInputStream reader = new BufferedInputStream(socket.getInputStream());
int dt;   
String cmd = "";

while( (dt = reader.read()) >= 0){
  cmd += (char)dt == '\n' || (char)dt == '\r' ? ' ' : (char)dt; // add each byte read to the string 
  System.out.println(cmd);
}

processaInput(cmd);

问题是函数processaInput永远不会被调用,就像程序卡在循环中一样。但更奇怪的是,由于system.out.println在流结束后停止被调用,因此不会停留在循环上。顺便说一句,这一次是在一个Thread(run()函数)中运行,不知道这是否会搞砸所以我在这里添加了这个最后的信息。无论如何,我在这里失踪了什么?感谢。

修改:没有客户端代码,因为我正在使用谷歌的应用POSTMAN来测试它,所以它只是向我的程序发送HTTP请求。

1 个答案:

答案 0 :(得分:3)

您正在将“请求结束”与“流结束”混为一谈。

套接字上的

'流结束'表示对等方已关闭连接。没有结束,没有同伴关闭。如果您计划在此套接字上写回一个响应,那么首先尝试将其读取到流的末尾是不正确的。

您正在尝试阅读单个请求,在这种情况下,您需要在应用程序协议中使用某些内容来告诉您何时拥有所有请求:行;长度字前缀;像XML这样的自描述协议; STX / ETX;类型长度值; ...

在这种情况下,如果协议是HTTP,则需要实现Content-length标头:识别它,读取到标头的末尾,然后从流中精确读取许多字节,例如:与DataInputStream.readFully()