2

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.

PoriPiriPuri
  • 43
  • 1
  • 4

1 Answers1

1

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.

Some Name
  • 8,555
  • 5
  • 27
  • 77
  • So the thing is that with Sockets I can't exploit zero copies between channels, which in theory are more efficient than reading data from the FileChannel into user space and then writing it into the Socket. As I said in the op, right now I'm using simple blocking Sockets. I was wondering if it would make sense to switch to ServerSocketChannels and SocketChannels in blocking mode just as if I was using simple Sockets, without using NIO selectors. – PoriPiriPuri Feb 11 '19 at 12:53
  • @PoriPiriPuri it does make sense if you want to keep data to be transferred off-heap via `DirectBuffer`s imposing almost no pressure on GC. `OutputStream` operates on `byte[]` which is on-heap by definition. So if you read data from `FileChannel` to direct buffer and want to transfer to Socket's `OutputStream` you would have to perform unnecasary copy. Anyway if you dont have to encrypt/compress or operate on the data in the user space transferring in-kernel ought to be more efficient. – Some Name Feb 16 '19 at 19:12