是否可以直接从文件写入套接字?

时间:2017-03-20 15:32:56

标签: c file sockets buffer

我对Web服务器的基本原理感兴趣,比如Apache或Nginx,所以我现在正在开发自己的服务器。

当我的服务器收到请求时,它正在搜索文件(例如index.html),如果它存在 - 将所有内容读取到缓冲区(content)并将其写入后面的插座。这是一个简化的代码:

int return_file(char* content, char* fullPath) {
    file = open(fullPath, O_RDONLY);
    if (file > 0) { // File was found, OK
      while ((nread = read(file, content, 2048)) > 0) {}
      close(file);
      return 200;
    }
}

问题很简单:是否可以避免使用缓冲区并直接将文件内容写入套接字?

感谢您的任何提示:)

3 个答案:

答案 0 :(得分:4)

没有可以直接从文件写入套接字的标准化系统调用。

但是,某些操作系统确实提供了这样的呼叫。例如,FreeBSD和Linux都实现了一个名为sendfile的系统调用,但两个系统之间的精确细节不同。 (在这两种情况下,您都需要文件的基础文件描述符,而不是FILE*指针,尽管在这两个平台上您都可以使用fileno()FILE*中提取fd。)

了解更多信息:

答案 1 :(得分:3)

你可以做的是写" chunk "你立即给客户看了。

为了编写内容,你必须阅读它,所以你不能避免这样做,但你可以使用一个较小的缓冲区,并在阅读时写入内容,无需将整个文件读入存储器中。

例如,你可以

unsigned char byte;
// FIXME: store the return value to allow
//        choosing the right action on error.
//
//        Note that `0' is not really an error.
while (read(file, &byte, 1) > 0) {
    if (write(client, &byte, 1) <= 0) {
        // Handle error.
    }
}

但是,unsigned char byte;可能是unsigned char byte[A_REASONABLE_BUFFER_SIZE];哪个更好,而且您不需要将所有内容存储在内存中。     }

答案 2 :(得分:0)

不,不是。必须有一个用于读/写数据的中间存储。

有一个边缘情况:当您使用内存映射文件时,映射文件的区域可用于写入套接字。但在内部,系统无论如何都会执行读入内存缓冲区操作。