如何使用sendfile接收文件?

Lyn*_*ton 5 c sockets linux

使用sendfile发送文件很容易:

stat(fd,&filestat);
sendfile(sockfd,fd,0,filestat.len)
Run Code Online (Sandbox Code Playgroud)

但是如何使用sendfile接收文件?由于我不知道文件的长度,我应该先发送文件的长度吗?

 sendfile(fd, sockfd,0, ??)
Run Code Online (Sandbox Code Playgroud)

似乎有两种方法可以做到这一点:

  1. 首先发送filestat.len

    //send end
    write(sockfd,filestat.len);
    sendfile(sockfd,fd,&offset,filestat.len);
    //receive end
    read(sockfd,&len);
    sendfile(fd,sockfd,&offset,len)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在接收端使用循环:

    //receive end
    while(sendfile(fd,sockfd,&offset,BUF_LEN) > 0) {
        offset += BUF_LEN;
    }
    
    Run Code Online (Sandbox Code Playgroud)

哪一个更好?我应该专门处理缓冲区长度吗?文件很大时,第一种方法是否有问题?

(我真的很喜欢sendfile的mac os版本,如果count为0,它将一直发送到文件末尾)

pou*_*def 4

这是一个很好的问题!

其他海报是正确的:您可以重复调用read()recv()有什么区别?),直到其中任何一个返回 0,这表示文件结束 (EOF)。

然而!作为一个好的做法,您应该考虑首先传递文件的大小。这将允许您的客户端准确预测有多少数据通过套接字,弄清楚(例如)是否有足够的磁盘空间等。它允许您在提交下载服务器的任何内容之前进行某种健全性检查尝试发送。

(这有其自身的危险。如果服务器发送错误的大小怎么办?)

您还可以考虑分块发送文件。这样,如果出现中断,您可以更精确地计算已传输的金额。(内核无论如何都会为你做这件事。但值得深思。)

通过网络发送单个整数(文件大小)并不太困难,但是如果您非常担心可移植性,则需要注意一些技巧。

祝你好运!