14

sendfile() can be used to transmit data from a "file" descriptor to a "socket" descriptor in order to get data from machine A to machine B. Is it possible to get the data at the receiving end from the "socket" descriptor to a file with similar zero-copy semantics? I think sendfile() doesn't help here because sendfile() needs the source of data to be "page/buffer" cache. Is my understanding correct? Can splice() help in this situation?

Mat
  • 202,337
  • 40
  • 393
  • 406
user880946
  • 429
  • 1
  • 5
  • 5

1 Answers1

17

You're correct about the limitation of sendfile for this. And yes, splice can help, but it's not trivial: splice requires that at least one of the source or target file descriptors be a pipe. So you can't directly splice from a socket to a plain file descriptor.

Conceptually, what you can do to make it work is:

  • setup your inbound socket fd and your output file fd as you would normally
  • create a pipe with pipe(2)
  • in a loop:
    • read from the socket to the write side of the pipe with splice
    • write from the read side of the pipe to the file with splice also

Repeat the last steps until all the data is read.

Zero-Copy in Linux with sendfile() and splice() has an implementation of this technique.

Mat
  • 202,337
  • 40
  • 393
  • 406
  • 7
    Since 2.6.33 the out_fd for sendfile can be any file descriptor (not just sockets). – ldrg Oct 17 '13 at 07:41
  • 3
    since 4.2 the same goes for `splice()` – technosaurus Oct 10 '15 at 05:22
  • 2
    @techno Man pages I can locate for `splice()` still say fd_in or fd_out needs to be a pipe. Do you have a reference? – Greg Aug 02 '18 at 02:03
  • 1
    @Greg https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2b514574f7e88c8498027ee366fd6e7aae5aa4b5 – technosaurus Aug 02 '18 at 19:17
  • 3
    @technosaurus that commit deals with splice from unix domain socket _to pipe_ hence doesn't contradict the statement, and splice does in fact (today, in kernel 5.1.3) still require either fd_in or fd_out (or both) to be a pipe – Matthijs May 17 '19 at 13:06