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

Is it possible to write directly from file to the socket?

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

当我的服务器收到请求时,它正在搜索一个文件(例如 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;
    }
}

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

感谢任何提示:)

你能做的就是将你立即阅读的“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]; 哪个更好,而且您不需要将所有内容都存储在内存中。 }

不,不是。必须有用于 reading/writing 数据的中间存储。

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

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

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

更多信息: