Java NIO:transferFrom直到流结束

aio*_*obe 16 java nio filechannel socketchannel

我正在玩NIO库.我正在尝试在端口8888上侦听连接,一旦接受连接,就从该通道转储所有内容somefile.

我知道该怎么做ByteBuffers,但我想让它与所谓的超高效工作FileChannel.transferFrom.

这就是我得到的:

ServerSocketChannel ssChannel = ServerSocketChannel.open();
ssChannel.socket().bind(new InetSocketAddress(8888));

SocketChannel sChannel = ssChannel.accept();
FileChannel out = new FileOutputStream("somefile").getChannel();

while (... sChannel has not reached the end of the stream ...)     <-- what to put here?
    out.transferFrom(sChannel, out.position(), BUF_SIZE);

out.close();
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是:如何表达" transferFrom某个频道,直到到达流末端"


编辑:将1024更改为BUF_SIZE,因为所使用的缓冲区大小与问题无关.

bes*_*sss 11

处理案件的方法很少.一些背景信息如何在内部实现trasnferTo/From以及何时可以实现.

  • 首先,你应该知道你需要多少字节,即FileChannel.size()用来确定可用的最大值并对结果求和.案件指的是FileChannel.trasnferTo(socketChanel)
  • 该方法不返回-1
  • 该方法在Windows上进行模拟.Windows没有从filedescriptor到socket xfer的API函数,它确实从name指定的文件中有一(2)到xfer - 但这与java API不兼容.
  • 在Linux上,使用标准的sendfile(或sendfile64),在Solaris上调用它sendfilev64.

简而言之for (long xferBytes=0; startPos + xferBytes<fchannel.size();) doXfer(),将从文件 - >套接字转移.没有OS函数从socket转移到文件(OP感兴趣).由于套接字数据不是操作系统缓存,因此无法有效地完成,它是模拟的.实现副本的最佳方法是使用带有套接字读缓冲区的轮询直接ByteBuffer标准循环.因为我只使用涉及选择器的非阻塞IO.

话虽这么说:我想让它与所谓的超高效"? - 它效率不高并且它在所有操作系统上模拟,因此当套接字正常关闭时它将最终转移.该功能将如果有任何转移(如果套接字是可读和打开的),甚至不抛出继承的IOException.

我希望答案是明确的:File.transferFrom当源是文件时,会发生唯一有趣的用法.最有效(也是最有趣的情况)是file-> socket和file-> file通过filechanel.map/ unmap(!!)实现.

  • 这全都是题外话。用户已经指定了他的要求。 (2认同)

Mar*_*aux 4

我不确定,但 JavaDoc 说:

尝试从源通道读取最多 count 个字节,并将它们从给定位置开始写入该通道的文件调用此方法可能会也可能不会传输所有请求的字节;是否这样做取决于通道的性质和状态。如果源通道的剩余字节数少于 count 个字节,或者源通道是非阻塞的并且其输入缓冲区中立即可用的字节数少于 count 个字节,则传输的字节数将少于请求的字节数。

我想你可能会说告诉它复制无限字节(当然不是在循环中)就可以完成这项工作:

out.transferFrom(sChannel, out.position(), Integer.MAX_VALUE);
Run Code Online (Sandbox Code Playgroud)

所以,我想当套接字连接关闭时,状态将会改变,这将停止该transferFrom方法。

但正如我已经说过的:我不确定。