Java InputStream到OutputStream的非阻塞回显

时间:2013-03-22 18:37:53

标签: java tcp stream echo

它建立了以下代码,似乎运作良好:

void pipe(InputStream, OutputStream os) {
  try {
    try {
      byte[] buf = new byte[1024*16];
      int len, available = is.available();
      while ((len = is.read(buf, 0, available > 0 ? available : 1)) != -1) {
        os.write(buf, 0, len);
        available = is.available();
        if(available <= 0)
          os.flush();
      }
    } finally {
      try {
        os.flush();
      } finally {
        os.close();
      }
    }
  } finally {
    is.close();
  }
}

在过去,我发现如果我调用is.read(buf),那么,即使数据可用,它也会阻止等待更多数据,直到缓冲区已满。这是一个用于TCP数据的echo服务器,所以我的要求是在新数据到达后立即进行刷新。

我的第一个解决方案是一次一个低效is.read()。后来,当这还不够好时,我正在查看可用的方法并找到is.available()。 API声明:

  

单个读取或跳过这么多字节不会阻塞。

所以我现在有一个非常好的解决方案,但对我来说一件坏事就是我如何处理is.available() == 0的情况。在这种情况下,我只是读取一个字节作为等待新数据可用的方式。


将数据从InputStream传输到OutputStream的推荐方法是什么?在数据到达时立即刷新?以上代码是否真的是正确的方式,或者我应该更改它,还是使用一些全新的代码?也许我应该使用一些较新的异步例程,或者可能有一个内置的Java方法呢?

1 个答案:

答案 0 :(得分:2)

  

在过去,我发现如果我调用is.read(buf),那么,即使数据可用,它也会阻止等待更多数据,直到缓冲区已满。

不,你没有。 TCP无法正常工作;套接字无法正常工作;和Java套接字不起作用。你错了。

这比你想象的要简单得多:

while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}
out.close();
in.close();

套接字输入/输出流没有缓冲,因此一旦读取它就会写入所有内容。

在这种情况下或几乎在任何情况下调用available()都是完全浪费时间。

这也是将任何类型的输入流复制到Java中任何类型的输出流的方法。

如果您想要非阻止代码,请使用NIO。但我不认为你真的这么做。