Search code examples
javafilesocketsniofilechannel

Transerring files between FileChannel and Socket


I'm writing a multithreaded server in Java. The server transfers files from/to clients. A requirement of the project is to use NIO to handle files.

Since the server is multithreaded, I'm not using SocketChannels for the communication, instead I'm using simple Sockets.

To meet the NIO requirement, I'm forced to use FileChannels to read from / write to files. Now the question is: does it make sense to transfer files between a FileChannel and something that isn't a channel (like a simple Socket)? Do I have to switch to SocketChannels?

I'm asking this because I've always seen that transfers like these are always made between two channels, so I was a little dubious about it.


Solution

  • does it make sense to transfer files between a FileChannel >and something that isn't a channel (like a simple Socket)?

    Yes, it does.

    FileChannel, Socket and SocketChannel are Java language abstraction over low level OS syscalls. I don't know how it works on other OS, but on Linux and (probably some other POSIX compliant OSes) it is implemented through read/write/sendmsg/etc.. syscalls. If you are using NIO selectors it is mostly likely delegated to epolling file descriptor. Take a look at EPollSelectorProvider.

    Do I have to switch to SocketChannels?

    Depends. NIO has support of zero-copy file: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/nio/channels/FileChannel.html#transferTo(long,long,java.nio.channels.WritableByteChannel) . Linux does support this through sendfile syscall: http://man7.org/linux/man-pages/man2/sendfile.2.html

    It would give you the ability to allow in-kernel file transferring avoiding unnecessary read-write from file and to socket. AFAIK such zero-copy transferring cannot be done in Java if you use plain Sockets.