我对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;
}
}
问题很简单:是否可以避免使用缓冲区并直接将文件内容写入套接字?
感谢您的任何提示:)
答案 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)
不,不是。必须有一个用于读/写数据的中间存储。
有一个边缘情况:当您使用内存映射文件时,映射文件的区域可用于写入套接字。但在内部,系统无论如何都会执行读入内存缓冲区操作。