我有一个小程序,它首先向用户输出一个字符串,然后接受一个输入。相反,我希望程序通过从端口发送和接收来工作。为了尝试实现这一点,我运行了命令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
触发刷新(因为它是行缓冲的):如果将输出重定向到文件,您将看到不同的行为:
当你没有运行
socat
时pts
,输出流处于块缓冲模式;当您使用pts
输出流运行它时,它处于行缓冲模式。如果您想覆盖该行为,您有几个选择。您可以调用函数来显式刷新任何缓冲数据:
或者,您可以在调用之前显式设置输出流的缓冲模式
printf
:有关更详细的解释,请参阅 Robert Love 的书Linux System Programming的第 3 章。