¿Cómo recibir un archivo usando sendfile?

send a file with sendfile is easy:


but how to receive a file using sendfile? since I don't know the length of the file, should I send the file length first?

 sendfile(fd, sockfd,0, ??)

There seems to be two ways of doing this:

  1. send the filestat.len first

    //send end
    //receive end
  2. use a loop in the receive end:

    //receive end
    while(sendfile(fd,sockfd,&offset,BUF_LEN) > 0) {
        offset += BUF_LEN;

Which one is better? Should I handle the buffer length specifically? Is there any problem in the first way when the file is quite large?

(I really like the mac os version of sendfile, it will send till the end of file if count is 0)

preguntado el 27 de noviembre de 13 a las 06:11

Why not use an existing protocol that has mechanisms for specifying data length, rather than making up your own? -

@Ignacio Vazquez-Abrams which protocol do you mean? -

4 Respuestas

¡Esta es una gran pregunta!

The other posters are correct: you could call leer() or recv () (cuál es la diferencia?) repeatedly until either of those returns 0, which indicates end of file (EOF).

However! You should consider first passing the size of the file, as a good practice. This would allow your client to anticipate exactly how much data is coming through the socket, figure out if (for example) there is enough disk space, etc. It allows you to have some sort of sanity-checking before committing to downloading whatever the server tries to send.

(This has its own perils. What if the server sends the wrong size?)

You might also consider sending the file in chunks. This way, if there is an interruption, you have a greater granularity when figuring out how much you've transferred. (The kernel does this for you anyway. But food for thought.)

Sending a single integer (a file size) over the network isn't too difícil, pero hay algunos trucos to be aware of if you are very worried about portability.

¡Buena suerte!

contestado el 23 de mayo de 17 a las 13:05

According to manual to sendfile():

       If  the  transfer was successful, the number of bytes written to out_fd
       is returned.  On error, -1 is returned, and errno is set appropriately.

So just use it in a way you use read() for sockets: repeat reading as much as you need until the whole amount of data you need will be read. Sure, paying attention to the cases of -1 and 0 results.

respondido 27 nov., 13:07

I guess using sendfile to receive a file from a socket fd is not possible, as according to man page:

The in_fd argument must correspond to a file which supports mmap(2)-like operations (i.e., it cannot be a socket).

I tried using it but got an error of Illegal seek

If anyone's interested, I can post snippets of my code.

Respondido 10 ago 19, 08:08

Good catch, you made me re-read the manual page. - Armén Michaeli

If you are a socket on the receiving end of the sendfile it is no different than any other TCP connection. When you reach eof your read or receive will return 0 bytes read. If there is socket communication that precedes and succeeds the sendfile data then, yes, you need some kind of agreed protocol so each side can make sense of what they are sending and receiving.

respondido 27 nov., 13:07

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.