Perl 创建软件路由器

Perl 创建软件路由器,perl,tk,inet,Perl,Tk,Inet,我想建立一个软件路由器 我已经编写了打开套接字、接收数据并打印其接收数据的代码。GUI将使用 下面是一个简单版本的代码,它基本上完成了我想要做的事情,除了没有分叉新的_-port子例程。每次我点击submit按钮,Tk窗口就会被卡住。如果有人可以帮助将fork添加到新的_-port子例程中,以便生成新的子进程。我的想法是我可以在表单中填写一个新端口并点击sumbit。窗口关闭后,我再次按下new(新建)按钮,插入一个新端口,现在第二个插座与第一个插座同时打开。即端口1234和5678同时被监听

我想建立一个软件路由器

我已经编写了打开套接字、接收数据并打印其接收数据的代码。GUI将使用

下面是一个简单版本的代码,它基本上完成了我想要做的事情,除了没有分叉新的_-port子例程。每次我点击submit按钮,Tk窗口就会被卡住。如果有人可以帮助将fork添加到新的_-port子例程中,以便生成新的子进程。我的想法是我可以在表单中填写一个新端口并点击sumbit。窗口关闭后,我再次按下new(新建)按钮,插入一个新端口,现在第二个插座与第一个插座同时打开。即端口1234和5678同时被监听

#!/usr/bin/perl -w
 use IO::Socket::INET;
 use Tk;

$myip = `ifconfig | grep -i inet | head -1 | cut -d ":" -f2 | cut -d " " -f1`;

sub new_port {
    my $socket = new IO::Socket::INET ( 
        LocalHost => "$myip",
        LocalPort => "$myport",
        Proto => 'tcp'
        Reuse => 1);
die "Cannot create socket on local host" unless $socket;
print "Server waiting for client connection on port $myport\n";

while(1)
{
 my $client_socket = $socket->accept();
 my $client_address = $client_socket->peerhost();
 my $client_port = $client_socket->peerport();
 my $input_data = "";
 my $received_data = "";
 do
 {
   $client_socket->recv($received_data, 65536);
   $input_data = $input_data . $received_data;
 } while ($received_data ne "");
 print "INPUT----------------------------------\n";
 print "Data from $client_address on port $client_port\n";
 print $input_data;
 shutdown($client_socket, 1);
  }
 }

 sub new_port_window {
   my $sw = MainWindow->new;
   $sw->geometry("200x100");
   $sw->title("port opener");
   $sw->Label(-text "Insert port #")->place(-anchor => 'center', -relx => 0.5, -rely => 0.2);
   $sw->Entry(-bg => 'white', -fg => 'black', -textvariable => \$myport)->place(-anchor => 'center', -relx => 0.5, -rely => 0.4);
   $sw->Button(-text "submit", -command => sub{new_port})->place(width => 100,
   -anchor => "center",
   -relx => 0.5,
   -rely => 0.8);
}

 my $mw = MainWindow->new;
       $mw->geometry("150x100");
       $mw->title("GUI TEST NEW FUNCTION");
       $mw->Label(-text => "click new")->place(-anchor => "center", -relx => 0.5, -rely => 0.3);
       $mw->Button(-text => "NEW", -command =>sub{new_port_window})->place(-width => 50, -anchor => "center", -relx => 0.5, -rely => 0.8);
MainLoop;

因此,我通过大量的实验使这项工作得以进行。诀窍是分叉子例程并将pid存储在一个文件中,以便在以后用于终止进程,该进程由于处于无限循环中而永远不会退出

Sub forker {
     $pid = fork ();
      if ( $pid == 0 ) {
          new_port();
      }
      my $pid_file = 'router.pid';
      open (my $pidlog, '>>', $pid_file) or die "cannot open file";
       print $pidlog "$pid\n";
       close $pidlog;
  }

注意:因为您没有提供任何代码,所以这个问题可能会以如下方式结束。无论如何,有关进程间通信的信息,请参阅。您不能阻止Tk的事件循环。您将工作委托给子任务的想法是好的,因为替代方法是尝试从Tk的事件循环中工作,我不知道是否存在这样做的工具。请注意,子任务可以是线程,而不是进程。可以通过管道使用JSON向任务发送请求。至于任务,您还需要某种类型的事件循环。传统上,人们会使用IO::Select,但也可以使用IPC::Run和许多其他解决方案。我知道你可能不熟悉英语,但礼貌的做法是大写I,而不是在任何地方都使用I。你肯定知道这条规则吗?我对你的问题进行了编辑,使其更具可读性。你可以试试。通过这种方式,您可以同时侦听GUI事件和套接字事件,而无需阻塞。另请参见我在三个系统上尝试了
$myip=…
行。它可以在Linux上运行,但不能在NetBSD或FreeBSD上运行。当您拥有perl的全部功能时,这似乎有点复杂。