【问题标题】:How to receive a file using sendfile?如何使用 sendfile 接收文件?
【发布时间】:2013-12-12 16:53:27
【问题描述】:

使用 sendfile 发送文件很简单:

stat(fd,&filestat);
sendfile(sockfd,fd,0,filestat.len)

但是如何使用 sendfile 接收文件?因为不知道文件的长度,是不是要先发文件长度?

 sendfile(fd, sockfd,0, ??)

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

  1. 先发送文件stat.len

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

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

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

(我很喜欢mac os版本的sendfile,count为0时会一直发送到文件末尾)

【问题讨论】:

  • 为什么不使用具有指定数据长度机制的现有协议,而不是自己编写?
  • @Ignacio Vazquez-Abrams 你指的是哪个协议?

标签: c linux sockets


【解决方案1】:

我想使用 sendfile 从套接字 fd 接收文件是不可能的,根据手册页:

in_fd 参数必须对应于支持类似 mmap(2) 操作的文件(即,它不能是套接字)。

我尝试使用它但收到Illegal seek的错误

如果有人感兴趣,我可以发布我的代码的 sn-ps。

【讨论】:

  • 很好,你让我重新阅读了手册页。
【解决方案2】:

这是一个很好的问题!

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

但是!您应该考虑首先传递文件的大小,这是一种很好的做法。这将允许您的客户端准确预测有多少数据通过套接字,确定(例如)是否有足够的磁盘空间等。它允许您在承诺下载任何服务器之前进行某种完整性检查尝试发送。

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

您也可以考虑分块发送文件。这样,如果出现中断,您在确定转移的数量时就有了更大的粒度。 (无论如何,内核都会为您执行此操作。但值得深思。)

通过网络发送单个整数(文件大小)并不过分difficult,但如果您非常担心可移植性,则需要注意一些tricks

祝你好运!

【讨论】:

    【解决方案3】:

    如果您是发送文件接收端的套接字,则它与任何其他 TCP 连接没有什么不同。当您达到 eof 时,您的 readreceive 将返回读取的 0 个字节。如果在 sendfile 数据之前和之后有套接字通信,那么,是的,您需要某种约定的协议,以便每一方都能理解他们正在发送和接收的内容。

    【讨论】:

      【解决方案4】:

      根据说明书给sendfile()

      RETURN VALUE
             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.
      

      因此,只需按照您对套接字使用read() 的方式使用它:根据需要重复读取,直到读取所需的全部数据量。当然,注意 -1 和 0 结果的情况。

      【讨论】:

        猜你喜欢
        • 2018-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-22
        • 2019-04-09
        • 2018-02-25
        • 1970-01-01
        相关资源
        最近更新 更多