2013-03-14 3 views
1

Я пытаюсь передать открытое соединение сокетов TCP из программы Perl в качестве stdin и stdout во внешнее приложение в Windows, похожее на то, что inetd в мире Unix.Как передать открытый TCP-сокет из Perl в приложение Windows в качестве stdin и stdout

То, что я пробовал:

  1. "Заменить" стандартный ввод и стандартный вывод в гнездо с помощью open или POSIX::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. В Windows select работает только на сокетах.

Что делать, чтобы передать сокет внешнему приложению?

Кстати, я использую Strawberry Perl, а не ActiveState.

ответ

2

К сожалению, в Windows вы не всегда можете это сделать. После большой боли мы отказались от возможности достичь этого. См. Этот вопрос (Are TCP SOCKET handles inheritable?) для объяснения.

Это есть Возможно на складе Установка Windows: вы должны убедиться, что сокет TCP создан неперекрывающимся, что не является значением по умолчанию для функций WinSock. Затем он может быть помечен как наследуемый и установлен как stdin/stdout дочернего процесса.

Однако при использовании некоторых известных продуктов безопасности (брандмауэров, AV) это невозможно сделать, поскольку они подключают TCP-стек таким образом, чтобы предотвратить сокет сокета TCP должным образом.

На самом деле вы действительно можете наследовать трубы Windows, файловые дескрипторы и т. Д. Безопасно. Чтобы дать сокет ребенку, он должен сотрудничать с родителем, а не тупо воспринимать его как stdin. Родитель может запустить ребенка, использовать WSADuplicateSocket, чтобы дать сокету дочернему PID, передать данные о сокете ребенку (возможно, в дочерний stdin по именованному каналу). Затем ребенок восстанавливает сокет, используя переданные данные. Итак, если вы готовы перепрограммировать клиента, чтобы иметь представление о его родителях, это можно сделать.

Я не уверен, как это можно сделать на Perl, но см. this interesting example для стартера. Вам придется импортировать встроенную функцию WSADuplicateSocket и сделать это самостоятельно, я бы себе.

+0

Спасибо, похоже, что передача сокета с использованием 'WSADuplicateSocket' является единственной реальной опцией. – Joni

 Смежные вопросы

  • Нет связанных вопросов^_^