C, sendfile() and send() difference?

samsamara picture samsamara · Nov 4, 2012 · Viewed 21.4k times · Source

sendfile() copies data between two file descripters within kernel space. Somewhere I saw if you are writing a web server in C in linux you should use send() and recv() instead of using write() and read(). So is the send() use the kernel space as well?

Whatever I use for sending - sendfile() or send() - on the client side I'll be using recv() right?

On the flip side, man page says: "The only difference between send() and write(2) is the presence of flags. With a zero flags argument, send() is equivalent to write(2)."

Answer

Adam Rosenfield picture Adam Rosenfield · Nov 4, 2012

If fd is a socket file descriptor, then these system calls are identical:

  • send(fd, data, length, 0) is the same as write(fd, data, length)
  • recv(fd, data, length, 0) is the same as read(fd, data, length)

So, unless you need to set a non-zero flags parameter, it makes no difference whether you use send/recv or write/read.

The sendfile system call is an optimization. If you have a socket sockfd and a regular file filefd and you want to copy some file data to the socket (e.g. if you're a web server serving up a file), then you might write it like this:

// Error checking omitted for expository purposes
while(not done)
{
    char buffer[BUFSIZE];
    int n = read(filefd, buffer, BUFSIZE);
    send(sockfd, buffer, n, 0);
}

However, this is inefficient: this involves the kernel copying the file data into userspace (in the read call) and then copying the same data back into kernel space (in the send call).

The sendfile system call lets us skip all of that copying and have the kernel directly read the file data and send it on the socket in one fell swoop:

sendfile(sockfd, filefd, NULL, BUFSIZE);