我正在尝试将来自Perl程序的开放TCP套接字连接作为stdin和stdout传递给Windows上的外部应用程序,类似于Unix世界中的inetd。
我尝试过:
使用open
或POSIX::dup2
通过套接字“替换”stdin和stdout并调用exec:
# $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。
答案 0 :(得分:2)
可悲的是,在Windows上你不能总是这样做。经过巨大的痛苦,我们放弃了能够实现这一目标。请参阅此问题(Are TCP SOCKET handles inheritable?)以获得解释。
在库存Windows安装上 是可能的:您必须确保TCP套接字是非重叠创建的,这不是WinSock函数的默认设置。然后它可以被标记为可继承并设置为子进程的stdin / stdout。
但是,由于安装了某些着名的安全产品(防火墙,AV),因此无法执行此操作,因为它们会以防止TCP套接字正确继承的方式挂钩TCP堆栈。
您只能安全地继承Windows管道,文件句柄等。要给孩子一个套接字,它必须与父母合作,而不是愚蠢地接受它作为标准输入。父级可以启动子级,使用WSADuplicateSocket
将套接字提供给子级的PID,将套接字的数据传递给子级(可能通过命名管道传递给子级的stdin)。然后,孩子使用传递的数据重新构建套接字。因此,如果您愿意重新编程客户端以了解其父级,则可以完成。
我不确定如何在Perl上完成此操作,但请参阅this interesting example作为入门者。你必须导入本地WSADuplicateSocket
函数并自己动手,我想。