C
socat:EXEC 沒有正確中繼
我有一個小程序,它首先向使用者輸出一個字元串,然後接受一個輸入。相反,我希望程序通過從埠發送和接收來工作。為了嘗試實現這一點,我執行了命令
socat TCP4-LISTEN:1337,reuseaddr,fork EXEC:./program
。通過這個命令,我希望能夠執行nc 127.0.0.1 1337
並期望程序:
- 接收來自程序的消息
- 能夠提供輸入
- 失去聯繫
但是,當使用
socat
它執行程序時,就像這樣
- 提供輸入
- 從程序收到的消息
- 給另一個輸入
- 失去了連接
我不明白為什麼會這樣。我使用該
socat
命令有什麼問題嗎?如果是,請告訴我缺少/錯誤的內容。這是程序。
#include <stdio.h> void vuln(void) { printf("Input\n"); char buffer[256]; gets(buffer); // potential buffer overflow } int main(void) { vuln(); return 0; }
在 C 中,
printf
是緩衝 I/O 庫的一部分——寫入流的數據在記憶體中“緩衝”(即,不直接寫入核心)。預設情況下,
stdout
(printf
寫入數據的流)是行緩衝流,這意味著字節儲存在記憶體緩衝區中,直到將換行符寫入流(或者其他一些甚至觸髮刷新的事件)。如果標準輸出不與終端相關聯,
stdout
則為塊緩衝流,這意味著字節儲存在記憶體緩衝區中,直到緩衝區變滿。當您在終端執行程序時,
'\n'
呼叫中的printf
觸髮刷新(因為它是行緩衝的):$ ./a.out Input whatever-you-type $
如果將輸出重定向到文件,您將看到不同的行為:
Terminal 1 Terminal 2 -------------------- -------------------- $ ./a.out > /tmp/out $ cat /tmp/out $ type-input $ $ cat /tmp/out Input $
當你沒有執行
socat
時pts
,輸出流處於塊緩沖模式;當您使用pts
輸出流執行它時,它處於行緩沖模式。如果您想覆蓋該行為,您有幾個選擇。您可以呼叫函式來顯式刷新任何緩衝數據:
printf("Input\n"); fflush(stdout);
或者,您可以在呼叫之前顯式設置輸出流的緩沖模式
printf
:setvbuf(stdout, NULL, _IONBF, 0); // _IONBF = Unbuffered printf("Input\n");
有關更詳細的解釋,請參閱 Robert Love 的書Linux System Programming的第 3 章。