2017-03-20 91 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

不,它不是。必須有用於讀取/寫入數據的中間存儲器。

存在一個邊界情況:當您使用內存映射文件時,映射文件的區域可用於寫入套接字。但是在內部,系統無論如何都會執行對內存緩衝區操作的讀取。

相關問題