如何将打开的TCP套接字从Perl传递到Windows应用程序作为stdin和stdout

时间:2013-03-14 10:35:13

标签: windows perl sockets strawberry-perl

我正在尝试将来自Perl程序的开放TCP套接字连接作为stdin和stdout传递给Windows上的外部应用程序,类似于Unix世界中的inetd。

我尝试过:

  1. 使用openPOSIX::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";
    
  2. 使用IPC::open3

    my $pid = open3(
        '>&'.$socket->fileno, 
        '<&'.$socket->fileno, 
        '<&'.fileno(STDERR), 
        $program);
    waitpid $pid, 0;
    
  3. 在这两种情况下,执行的程序都会收到一些不是套接字的东西(可能是管道?),这是一个问题,因为它想要使用select。在Windows上select仅适用于套接字。

    如何将套接字传递给外部应用程序?

    顺便说一句,我使用的是Strawberry Perl,而不是ActiveState。

1 个答案:

答案 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函数并自己动手,我想。