我正在尝试将来自 Perl 程序的开放式 TCP 套接字连接作为 stdin 和 stdout 传递到 Windows 上的外部应用程序,类似于 Unix 世界中的 inetd。
我尝试过的:
使用
open
或POSIX::dup2
并调用 exec 将 stdin 和 stdout 替换为套接字:# $socket is an open TCP socket open STDIN, '<&', $socket or die "Unable to dup stdin: $^E"; open STDOUT, '>&', $socket or die "Unable to dup stdout: $^E"; close $socket; exec($program) or die "Unable to exec $command: $^E";
使用
IPC::open3
:my $pid = open3( '>&'.$socket->fileno, '<&'.$socket->fileno, '<&'.fileno(STDERR), $program); waitpid $pid, 0;
在这两种情况下,执行的程序都会收到一些不是套接字(也许是管道?)的东西,这是一个问题,因为它要使用select
。在 Windows 上,select
仅适用于套接字。
如何将套接字传递给外部应用程序?
顺便说一下,我使用的是 Strawberry Perl,而不是 ActiveState。
最佳答案
遗憾的是,在 Windows 上您不能总是这样做。在经历了巨大的痛苦之后,我们放弃了能够实现这一目标。请参阅此问题 ( Are TCP SOCKET handles inheritable?) 以获取解释。
它是在标准的 Windows 安装上是可能的:您必须确保创建的 TCP 套接字是非重叠的,这不是 WinSock 函数的默认设置。然后它可以被标记为可继承的并设置为子进程的标准输入/标准输出。
但是,如果安装了某些知名的安全产品(防火墙、AV),则无法执行此操作,因为它们以阻止 TCP 套接字被正确继承的方式挂接 TCP 堆栈。
您只能真正安全地继承 Windows 管道、文件句柄等。要给 child 一个套接字,它必须与 parent 合作,而不是愚蠢地接收它作为标准输入。 parent 可以启动 child ,使用WSADuplicateSocket
将套接字提供给 child 的 PID,将有关套接字的数据传递给 child (可能通过命名管道传递给 child 的标准输入)。然后 child 使用传递的数据重建套接字。因此,如果您愿意重新编程客户端以了解其父级,则可以做到。
我不确定如何在 Perl 上完成此操作,但请参阅 this interesting example首先。我想,您必须导入 native WSADuplicateSocket
函数并自行完成。
关于windows - 如何将打开的 TCP 套接字作为标准输入和标准输出从 Perl 传递到 Windows 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15406830/