2011-12-18 99 views
1

所有,我設計一個key-value服務器,當我寫的客戶端,我發現了一個很奇怪的東西,看到了簡化代碼:關於在unistd.h中讀()(C++)

while(1) 
{ 
    printf("->:"); 
    read(STDIN_FILENO, buf, sizeof(buf)); 
    write(client_sock, buf, sizeof(buf)); 
    int m = read(client_sock, buf, sizeof(buf)); 
    buf[m] = '\0'; 
    printf("%s", buf); 
} 

當我運行程序時,它首先要求輸入,所以我輸入了一些東西,但什麼也沒有發生! (服務器運行良好,這也呼應的東西,當我使用其他客戶端)

然後我改變了只有一行代碼:

printf("\n->:"); 

那麼它運行良好!爲什麼?爲什麼「\ n」可以改變輸出?我想這可能是read(),但我無法解釋它

回答

5

printf(3)是C標準IO庫的一部分,它執行內部緩衝以提供性能改進。

緩衝有三種類型:無,行和塊。

應用哪個緩衝區部分取決於要寫入的描述符是否爲2,以及是否連接到終端。 (請參閱isatty(3)。)

如果打印完成到stderr(2),則不執行緩衝。

如果打印做是爲了任何其他描述符,則該行爲的變化,如果它是一個終端或不:如果輸出是終端,則輸出是行緩衝。如果輸出是而不是終端(文件,管道,插座等),那麼輸出是塊緩衝

當行緩衝時,它在打印任何內容之前等待\n。 (或者,如果你寫夠發送\n之前溢出內部緩衝區)

我會建議,而不是如下:

printf("->:"); 
fflush(stdout); 
read(STDIN_FILENO, buf, sizeof(buf)); 
/* ... */ 
printf("%s\n", buf); 

這是一個小的變化;你不會在程序啓動時得到一個毫無意義的空行,並且提示應該立即顯示出來..

可以使用setvbuf(3)功能改變緩衝自己的視頻流一次,在啓動時,永遠需要再次刷新它,如果你寧願。

int err = setvbuf(stdout, NULL, _IONBF, 0); 
/* check err */ 
+0

很好的解釋。 – 2011-12-18 06:16:08

+0

非常感謝,這很有幫助 – Flypig 2011-12-18 07:06:09

3

默認情況下,標準輸出是行緩衝的。如果你沒有寫完整的一行,輸出將保存在緩衝區中,直到你完成。您可以使用fflush刷新流或setbuf以更改緩衝模式。