InputStream in.read() 的行为与预期不同

InputStream in.read() behaving differently than expected

我正在尝试使用 TCP 将文本文件传输到另一台服务器,但它的行为与预期不同。发送数据的代码是:

        System.out.println("sending file name...");
        String outputFileNameWithDelimiter = outputFileName + "\r\n"; //These 4 lines send the fileName with the delimiter
        byte[] fileNameData = outputFileNameWithDelimiter.getBytes("US-ASCII");
        outToCompression.write(fileNameData, 0, fileNameData.length);
        outToCompression.flush();

        System.out.println("sending content...");
        System.out.println(new String(buffer, dataBegin, dataEnd-dataBegin));
        outToCompression.write(buffer, dataBegin, dataEnd-dataBegin); //send the content
        outToCompression.flush();

        System.out.println("sending magic String...");
        byte[] magicStringData = "--------MagicStringCSE283Miami".getBytes("US-ASCII"); //sends the magic string to tell Compression server the data being sent is done
        outToCompression.write(magicStringData, 0, magicStringData.length);
        outToCompression.flush();

因为这是 TCP,你不能像在 UDP 中那样发送离散数据包,我希望所有数据都在输入流中,我可以只使用定界符来分隔文件名、内容和结束字符串然后每个 in.read() 只会给我下一个后续数据量。

相反,这是我每次读取时获得的数据:

On the first in.read() byteBuffer appears to only have "fileName\r\n". 
On the second in.read() byteBuffer still has the same information. 
On the third in.read() byteBuffer now holds the content I sent. 
On the fourth in.read() byteBuffer holds the content I sent minus a few letters.
On the fifth in.read() I get the magicString + part of  the message.

每次从网络服务器发送时我都会刷新,但输入流似乎没有实现可刷新。

谁能解释为什么会这样?

编辑: 这就是我读入内容的方式。基本上这是一个循环,然后写入文件。

 in.read(byteBuffer, 0, BUFSIZE);

如果您的期望是读取将填充缓冲区,或者接收到由对等方发送的单个 write() 所发送的内容,那么您的期望在这里有问题,而不是 read().未指定一次传输超过一个字节,并且无法保证保留写入边界。

如果不将 read() 的结果存储到变量中,就不可能编写正确的代码。

当您从 InputStream 中读取数据时,您将给它一个要写入的字节数组(以及可选的偏移量和要读取的最大数量)。 InputStream 不保证数组将填充新数据。 return值为实际读入的字节数。

您的示例中发生的情况是这样的:

  • 第一个 TCP 数据包来自 "fileName\r\n",被写入您的缓冲区,到目前为止一切正常。
  • 您再次调用 read(),但下一个数据包尚未到达。 read() 将 returned 0,因为它不想阻塞直到数据到达。所以缓冲区仍然包含"fileName\r\n"。编辑:正如所指出的,read() 总是阻塞,直到它读取至少一个字节。真的不知道为什么缓冲区没有改变。
  • 读到第三遍,内容到了
  • 内容的第一位被消息的第二部分覆盖,最后一位仍然包含旧消息的一部分(我想这就是你的意思)。
  • 等等,你懂的

您需要检查 return 值,等待数据到达,并且只使用最后一个 read() 写入的缓冲区。