I have to transfer ~100MB of data over ServerSocket using NIO, but I can't figure out how to do this without transfer breaking at any place / keeping the state of transfer.
My first idea was to send the size of file, apparently I can't send size of that big files because it wont even fit on RAM at once. Then I thought, why not just transfer til nothing is received, but thats when problem comes in.
Even if I am writing server-sided data all the time
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();
}
but because there have to be breaks in file transfer some time reading the data constantly and breaking when nothing is available was bad idea.
I can't figure out how could I possibly tell the client if theres still data available without having to send each slice of data as new packet with opcode etc., or is it even possible?
I am also wondering if theres better way to send whole buffer than below
while(channel.write(buffer) > 0);
Maybe you are looking for this:
channel.transferFrom(0, fc.size(), fc);
The correct way to copy channels via buffers is as follows:
while (in.read(buffer) >= 0 || buffer.position() > 0)
{
buffer.flip();
out.write(buffer);
buffer.compact();
}
This takes care of all the corner cases including read length != write length and having data left over at the end of the input.
NB that is for blocking mode. If you are in non-blocking mode you should return to the select()
loop if read() or write() returns zero.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With