我必须使用NIO通过ServerSocket传输~100MB的数据,但我无法弄清楚如何在没有任何地方的传输中断/保持传输状态的情况下执行此操作。
我的第一个想法是发送文件的大小,显然我无法发送大文件的大小,因为它甚至不能立即适应RAM。然后我想,为什么不只是转移直到没有收到,但那是问题进来。
即使我一直在编写服务器端数据
FileChannel fc = new FileInputStream(f).getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while(fc.read(buffer) > 0) {
buffer.flip();
while(channel.write(buffer) > 0);
buffer.clear();
}
但是因为文件传输必须中断一段时间不断地读取数据并在没有任何可用的时候断开是不好的主意。
我无法弄清楚我怎么可能告诉客户端是否仍有数据可用而不必将每个数据片段作为带有操作码等的新数据包发送,或者甚至是否可能?
我也想知道发送整个缓冲区的方式是否比下面更好
while(channel.write(buffer) > 0);
答案 0 :(得分:5)
也许你正在寻找这个:
channel.transferFrom(0, fc.size(), fc);
答案 1 :(得分:4)
通过缓冲区复制通道的正确方法如下:
while (in.read(buffer) >= 0 || buffer.position() > 0)
{
buffer.flip();
out.write(buffer);
buffer.compact();
}
这可以处理所有极端情况,包括读取长度!=写入长度并在输入结束时保留数据。
请注意,这是阻止模式。如果处于非阻塞模式,如果read()或write()返回零,则应返回select()
循环。
答案 2 :(得分:0)
如果您无法依赖套接字保持打开状态,则无法在协议中构建恢复并继续机制。至于告诉客户端需要多少字节,您可以使用File.length
找到文件大小而不将其读入内存。