2017-03-20 55 views
1

我对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; 
    } 
} 

的问题很简单:是否有可能避免使用缓冲区并直接写入文件内容的插座?

感谢您的任何提示:)

+1

我从来没有用过它,所以我不想写一个答案,但看一看['splice'](https://linux.die.net/人/ 2 /拼接)。这里的想法是做一个零拷贝传输,它至少可以节省将文件数据复制到用户空间的时间,然后再回到内核空间,然后到达插槽。您可以更多地了解零拷贝概念,并且有来自Linus的信息性电子邮件交换,在那里谈论“拼接”。我在这里与Linux交谈,不确定微软或其他人的作用是什么。 – yano

+1

@yano'splice'非常酷且一般,但在将文件发送到套接字的特定情况下,我相信'sendfile'更容易,效率更高。 – rici

+1

@rici啊是的,我同意,当然更容易。我的猜测是'sendFile'在引擎盖下使用'splice'(对于Linux而言),但我不知道。 – yano

回答

4

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

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

欲了解更多信息:

+0

“不可移植” - 'fileno'存在于POSIX.1-2001! –

+0

@Antti当然可以在posix实现之间移植。但它不可移植到非posix实现。 – rici

+0

但是,既不是套接字:) OP几乎肯定使用POSIX平台来编写代码。 –

3

您立即读取到客户端你可以做的是写了“”。

为了编写内容,您必须阅读它,所以您无法避免这种情况,但您可以使用较小的缓冲区,并在读取内容时编写内容,而不需要将整个文件读入内存。

举例来说,你可以

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];这将是更好的,你不需要存储在内存中的所有内容。 }

0

不,它不是。必须有用于读取/写入数据的中间存储器。

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

相关问题