1

我正在尝试将来自 Perl 程序的开放 TCP 套接字连接作为标准输入和标准输出传递到 Windows 上的外部应用程序,类似于 Unix 世界中的 inetd 所做的。

我试过的:

  1. open使用orPOSIX::dup2并调用 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;
    

在这两种情况下,执行的程序都会收到不是套接字的东西(也许是管道?),这是一个问题,因为它想使用select. 在 Windowsselect上仅适用于套接字。

我该怎么做才能将套接字传递给外部应用程序?

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

4

1 回答 1

2

可悲的是,在 Windows 上你不能总是这样做。经过巨大的痛苦,我们放弃了能够做到这一点。请参阅此问题(TCP SOCKET 句柄是否可继承?)以获得解释。

在普通的 Windows 安装上可能的:您必须确保创建的 TCP 套接字不重叠,这不是 WinSock 函数的默认设置。然后可以将其标记为可继承并设置为子进程的标准输入/标准输出。

但是,在安装了某些著名的安全产品(防火墙、AV)后,这是不可能的,因为它们以一种阻止 TCP 套接字被正确继承的方式挂钩 TCP 堆栈。

您只能安全地真正继承 Windows 管道、文件句柄等。要给孩子一个套接字,它必须与父母合作,而不是默默地接受它作为标准输入。父母可以启动孩子,用于WSADuplicateSocket将套接字提供给孩子的PID,将有关套接字的数据传递给孩子(可能通过命名管道传递给孩子的标准输入)。然后,孩子使用传递的数据重构套接字。因此,如果您愿意对客户端进行重新编程以了解其父级,则可以这样做。

我不确定如何在 Perl 上完成此操作,但请参阅这个有趣的示例作为入门。我想你必须导入本机WSADuplicateSocket函数并自己做。

于 2013-03-14T10:50:16.737 回答