【问题标题】:Redirect stdin and stdout in child in c在c中重定向孩子中的标准输入和标准输出
【发布时间】:2015-01-02 00:27:30
【问题描述】:

我需要创建一个客户端-服务器应用程序(使用套接字),基本思想是:

  • 客户端发送字符串
  • 服务器接收字符串并将其作为另一个应用程序的标准输入发送
  • 服务器读取应用程序的标准输出
  • 服务器向客户端发送应答。

“其他应用程序”是一个封闭源代码计算(从标准输入读取4 5 + 并打印9 的计算器)。

我正在尝试在服务器上创建一个双管道,fork,并使用此管道重定向计算的标准输入和标准输出:

if(!fork())
{

    close(STDOUT_FILENO);
    close(STDIN_FILENO);

    dup2(outfd[0], STDIN_FILENO);
    dup2(infd[1], STDOUT_FILENO);

    close(outfd[0]); /* Not required for the child */
    close(outfd[1]);
    close(infd[0]);
    close(infd[1]);

    system("./calc/calc ");
    exit(0);
}

从服务器写入一个管道并读取另一个管道

    close(outfd[0]); /* These are being used by the child */
    close(infd[1]);

    char c;
    do
    {
        c=getchar();
        write(outfd[1],&c,1);
    }while(c!='\n');
    input[read(infd[0],input,100)] = 0; /* Read from child’s stdout */

    printf("%s",input);

    close(outfd[1]);
    close(infd[0]);

我知道这很不完整,但我认为它至少应该打印 calc 中第一行的输出。

(完整代码)

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main()
{

int outfd[2];
int infd[2];

pipe(outfd); /* Where the parent is going to write to */
pipe(infd); /* From where parent is going to read */

if(!fork())
{

    close(STDOUT_FILENO);
    close(STDIN_FILENO);

    dup2(outfd[0], STDIN_FILENO);
    dup2(infd[1], STDOUT_FILENO);

    close(outfd[0]); /* Not required for the child */
    close(outfd[1]);
    close(infd[0]);
    close(infd[1]);

    //system("/usr/bin/bc -q");
    system("./calc/calc ");
    exit(0);
}
else
{

    char input[100];

    close(outfd[0]); /* These are being used by the child */
    close(infd[1]);

    //write(outfd[1],"2^32\n",5); /* Write to child’s stdin */
    //write(outfd[1],"2 4 +\n",6);
    char c;
    do
    {
        c=getchar();
        write(outfd[1],&c,1);
    }while(c!='\n');
    input[read(infd[0],input,100)] = 0; /* Read from child’s stdout */

    printf("%s",input);

    close(outfd[1]);
    close(infd[0]);

}
return 0;

这是非常基本的,但它只是用于测试。当我执行它时,它什么也不做。

如果我在执行过程中ps -e | grep calc,我可以看到它正在运行,但无论我输入什么似乎都没有做任何事情。

【问题讨论】:

  • 孩子可能正在缓冲它的输出。它会在退出时刷新输出,但在执行此操作之前它可能会在 stdin 上等待 EOF。
  • 它是你的calc 二进制文件吗?我可以针对常见的calc 安装编译和运行您的代码。

标签: c linux pipe


【解决方案1】:

尝试移动:

close(outfd[1]);

在do-while 循环和input[read(infd[0],input,100)] = 0; 之间。

这将在calc 的标准输入上发送EOF。它会退出,这会刷新它的输出缓冲区,所以会有一些东西要读取。

您的代码已死锁:您在关闭管道之前等待输出,但它在等待您在管道发送输出之前关闭管道。

【讨论】:

  • 您先生,真是个天才!我现在要在我计划使用的实际代码上尝试这个,但是在这个例子中它会产生奇迹!非常感谢!
  • 很抱歉再次给您带来麻烦,但是我可以在不关闭管道的情况下显示响应吗? (或者至少是事后重新打开它的一种方式)。非常感谢
  • 您无法重新打开管道。如果您尝试与应用程序执行多次交互,则需要让它在每次请求后刷新其缓冲区。这是否可行以及如何执行取决于应用程序的详细信息。如果您可以修改您正在与之交谈的程序,您可以使用setbuf() 禁用它的缓冲。如果它超出您的控制范围,您可能必须使用 pty。也许您应该考虑将控制程序编写为 Expect 脚本而不是 C。
  • 非常感谢!那 setbuf() 成功了!我仍然会寻找一个不涉及更改计算代码的替代方案,但现在这很好用!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多