C, sendfile() and send() difference?

c, linux, send, sendfile

Solution

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);

Problem

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)."

Original source