【问题标题】:How redirect stdout (stderr) of child process to socket in winapi?如何将子进程的stdout(stderr)重定向到winapi中的socket?
【发布时间】:2011-07-18 07:28:17
【问题描述】:

我想制作客户端-服务器程序,其中服务器是主进程,客户端是子进程。在客户端,我想将子进程的 stdout 和 stderr 流重定向到套接字。在服务器中,我想从套接字文件描述符中创建并从中读取。在互联网上有很多关于套接字的信息,但我没有找到任何通过 Windows 套接字的父子 IPC 示例。

如果可能,请在此处发布一个简单的代码来解决我的问题(或部分问题)。 msdn 的链接也有帮助,但我想我已经在那里查找了所有内容,但没有找到我想要的。

附:请不要推荐管道。我想通过套接字来做到这一点。

【问题讨论】:

  • 这将是非常具体的实现。我假设 Windows 是唯一的平台和操作系统要求。您愿意使用哪些编译器、IDE 和库?
  • 我正在使用视觉工作室。我想使用标准库和winapi,作为套接字我更喜欢socket2。但也可以使用 cygwin 库。
  • 您在哪些部分遇到问题 - 绑定 + 侦听套接字、连接套接字或重定向 IO?
  • 很讨厌告诉你这个坏消息,但是winsock没有办法将标准输出重定向到一个套接字,你必须使用管道和其他一些进程将数据从管道复制到套接字等。
  • @Mihran。好吧,我不明白。您可以编写一个客户端应用程序,但它会产生另一个不是您编写的应用程序?它是您想要捕获其标准输出/错误的客户端下的第二个应用程序?

标签: c++ c winapi client-server


【解决方案1】:

看看Netcat,如果你可以使用它,或者在sourceforge的某个地方找到windows版本的源代码,可能这可以使用管道来拦截标准输入/标准输出,并通过这些管道发送到套接字并从中读取。

我知道你说没有管道,但只有 Windows API 没有其他方法可以做到这一点。您可能至少需要以下内容:

CreatePipe

WriteFile

ReadFile

【讨论】:

  • 谢谢。但我已经通过管道做到了这一点))但还有其他问题。管道不支持 select() 这就是我需要套接字的原因。
  • 您可以使用重叠 I/O 模型和WaitForMultipleObjects 从多个管道中读取或管理。它不如套接字列表上的Select() 好,但它是一种伪造它的方式。您运行了多少客户端需要重定向到服务器?
  • 是的@AJG85 我也可以这样做。但这里还有另一个问题。如果我这样做,那么我需要以非阻塞模式读取表单管道。在 Windows 中,我无法使文件 HANDLES 成为非阻塞我只能通过低级 ReadFile 函数以非阻塞模式读取。但我想用这个句柄制作 FILE* 然后通过 fgets 读取。
  • ReadFileEx 专为异步调用而设计。将您的句柄传递给管道并使用OVERLAPPED 数据结构。您需要使用 WaitForMultipleObjects 保护访问权限,因此您无法完全避免阻止以防止 Bad Things™
  • 谢谢,但这无济于事。我有很多其他代码可以与 FILE* 一起使用,我应该从管道 FILE* 中生成,为此我使用 fgets 方法调用 ReadFile 没有重叠结构。
【解决方案2】:

这就像火灾发生后试图扑灭火灾,而您应该首先尝试防止火灾。

由于您是 server.exe 和 client.exe 的公开作者,而不是试图捕获 stdout/stderr,然后将其重定向到套接字,您应该重新设计客户端,以便您在发送到 stdout 之前捕获发往 stdout 的文本。

此时,您可以将输出文本发送到两个标准输出,如果您愿意,还可以发送到套接字。

编辑:忽略上半部分,因为您后来说您不是客户端的作者。

好的,第二次尝试:

既然您使用“假”客户端生成“真实”客户端,为什么不直接在“假”客户端的标准输入上拦截“真实”客户端的标准输出(打开管道)。然后让“假”客户端在套接字上发回数据..

【讨论】:

  • 我不是真实客户的作者。我只是假客户端的作者,它应该只连接到服务器,然后自己产生真正的客户端,必须重定向 stdout 和 stdoerr。
  • @J T 查看@AJG85s 回答的评论
  • 这个想法不是在客户端和服务器之间打开管道,而是在“假”客户端和“真实”客户端之间打开管道。 “假”客户端仍将通过套接字发送其数据,因此您的服务器仍可以多路复用所有传入请求并仅在一个进程上运行。
  • Chris 在下面的回答说明了我一直在谈论的内容。
  • @Mihran:我不明白,你非常不愿意追求管道路由,但回顾你过去的问题,你已经坚定地寻找如何使用异步管道实现 IO 重定向视窗。是什么赋予了?你为什么不和我们分享一下你为什么认为管道是一个糟糕的主意呢? (特别是因为您发布的代码示例表明这已经是您正在做的事情)。
【解决方案3】:

我知道支持这一点的唯一环境是 Cygwin。他们是开源的 - 尝试仔细阅读他们的代码以获得想法。不过,肯定会很讨厌,到处都是抽线之类的东西。

【讨论】:

    【解决方案4】:

    假设:

    server talks with client
    

    client spawns child
    

    这是一个来自 MSDN 的示例,用于创建 Child Process with Redirected IO

    很遗憾,您必须使用管道将 IO 从子程序获取到客户端。没有如果,ands 或 buts 关于它。

    然后您可以使用类似以下的方式将信息获取到服务器:

    客户端通讯循环:

    while ( /* files are open */ ) { 
        DWORD dwRead;  
        CHAR chBuf[1024]; memset(chBuf, 0, 1024); /* always initialize your memory! */
        BOOL bSuccess = FALSE;
    
        /* read data from child pipe */
        ReadFromFile(g_hSChildStd_IN_Rd, chBuf, 1024, &dwRead, NULL );      
    
        /* send data via windows sockets to the remote server connection 
           represented by serverSocketHandle */
        send(serverSocketHandle, chBuf, dwRead, 0);
    }
    

    实际上,您的客户端成为 STDOUT/ERR 管道和 TCP 套接字之间的转换器。

    【讨论】:

    • @Chris 你想说什么?
    • 我在问题中写了不建议管道。
    • Mihran,如果您无法修改可执行的“真实”客户端,则必须以某种方式拦截 STDOUT/ERR。你真的应该重新考虑使用管道。
    • @Mihran 他不是指 IPC 管道,而是指 IO 重定向——在命令行上你使用 | 执行并调用管道。他仍在使用 TCP(循环中的send
    • 您必须使用管道从您没有编写的程序中获取,然后您可以使用套接字写入您的服务器。
    猜你喜欢
    • 1970-01-01
    • 2012-07-14
    • 1970-01-01
    • 2015-08-18
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    • 2022-01-18
    • 2017-05-08
    相关资源
    最近更新 更多