Perl 代码使用 IO::SELECT 和 IO::Socket::UNIX 正常退出,但使用 NETCAT (nc) 不退出,为什么?

Perl code is exiting without an error using IO::SELECT and IO::Socket::UNIX but doesn't exit using NETCAT (nc) why?

看起来(对我来说)PERL 没有错误就崩溃了,但(对我来说)我一定是做错了什么。一切看起来都非常奇怪,因为 PERL exits 中间代码没有错误,它不应该......除非我错了......这可能是我......这就是为什么我正在寻求帮助!

我已经确认下面的代码与原始 CENTOS 8(我使用的是 Rocky)系统表现出相同的行为并且它 EXITS...请有人帮助我并解释为什么我真的不知道发生了什么,所以我正在寻求帮助!

两个简单的 PERL 程序:

   ./listen_socket.pl
   ./send_socket.pl sending_this

发送套接字实际上是一个简单的 netcat...nc。

NETCAT 有效....如果我使用:

  echo send_this | nc -U /tmp/whydontyouwork.sock

then "listen_socket.pl" 不会退出并按预期运行。 如果我执行这个:

./send_socket.pl send_this

然后就失败了。

我不明白为什么。 请帮助我并告诉我我在哪里是个白痴因为我不知道!

这是两个 perl 程序:(listen_socket.pl) 和 (send_socket.pl)

listen_socket.pl:

use warnings;
use IO::Select;
use IO::Socket::UNIX;

my $SOCK_PATH   = "/tmp/whydontyouwork.sock";
my $socket;
my $sel         = IO::Select->new();

unlink $SOCK_PATH;
setup();
main();

print STDERR "I know I never get here...see below..\n";


sub setup {
  $socket = new IO::Socket::UNIX(
      Type   => SOCK_STREAM,
      Local  => $SOCK_PATH,
      Listen => 5,
  );
  $sel->add($socket);
}

sub main {
  while ( 1 == 1 ) {
    while(my @ready = $sel->can_read(1)) {
      foreach my $fh (@ready) {
        if($fh == $socket) {
          # Create a new socket
          my $new = $socket->accept;
          $sel->add($new);
        }
        else {
          # Process socket
          if ( 1 == 1 ) {
            my $data = <$fh>;
            if ( defined $data ) {
              print STDERR "I am here...I GET HERE!!";
              print $fh "\n";
              print STDERR "..and all done and I NEVER GET HERE!!??.\n";
              $sel->remove($fh);
              $fh->close;
            }
          }
          print STDERR "Howdie here?   Nope..\n";
        }
      }
    }
  }
}

send_socket.pl:

#!/usr/bin/perl
use Socket;

my $SOCK_PATH = "/tmp/whydontyouwork.sock";

if ( $ARGV[0] ) {
    socket(CLIENT, PF_UNIX, SOCK_STREAM, 0);
    connect(CLIENT, sockaddr_un($SOCK_PATH));
    print CLIENT $ARGV[0] ;
    close CLIENT;
    exit;
}
exit 1;

作品==>
echo send_this | nc -U /tmp/whydontyouwork.sock 不工作 ==> perl ./send_socket.pl send_this

您应该添加每个 运行 的输出,至少告诉我们听众死于 Broken pipe 这会让您的问题更加明显。

无论如何,看起来您的发送方正在关闭套接字,然后侦听器正在尝试写入它。

从技术上讲,您可以忽略破损的管道,并通过将 $SIG{PIPE} = 'IGNORE'; 添加到侦听器来使 perl 示例的输出相同,但这当然不能解决(缺少)逻辑问题。

但是,实际上,您应该阅读更多有关使用套接字编程的内容,因为您尝试做的事情没有多大意义,而且,更重要的是,您实际上应该注意错误消息提示正在发生的事情。