无法从 perl 中的套接字读取 - 可能死锁?

发布于 2024-12-15 19:17:16 字数 2887 浏览 0 评论 0原文

我的操作系统是带有 perl 5.14.2 的 Archlinux。我只是想写一个小程序来完成远程编译。该程序只是将一个 C 源文件传递到服务器。服务器将调用gcc来编译C代码并传递编译器的消息。客户端收不到编译器的消息。我在服务器上有消息。 有代码:

#!/usr/bin/perl -w
# oj.pl --- alpha


use warnings;
use strict;
use IO::File;
use IO::Socket;

use  constant MY_TRAN_PORT => 138000;
$| = 1;


my $tmpFileToBeCompiled = IO::File->new ("> tmpFile09090989.c") or die "Can't creat this file";

#if (defined $tmpFileToBeCompiled) {
#    print $tmpFileToBeCompiled "argh";         # just for test!
#}
# $fihi->close;

my $port        = shift || MY_TRAN_PORT;

my $sock_server = IO::Socket::INET->new (Listen         => 20,
                                         LocalPort      => $port,
                                         Timeout        => 60,
                                         Reuse          => 1)
    or die "Can't create listening socket: $!\n";

my $tmp = 1;
while ($tmp) {
    next unless my $session = $sock_server->accept;

    my $peer = gethostbyaddr ($session->peeraddr, AF_INET)
        || $session->peerhost;
    warn "Connection from [$peer, $port]\n";

    while (<$session>) {
        print $tmpFileToBeCompiled $_;              # if it works, the filehandle should be changed into tmpFile.  just fixed.
        print $session "test!";

    }

    my @lines = `gcc tmpFile09090989.c 2>&1`;

    foreach ( @lines) {
        print $session  $_ . "test!!!\n";
     #   $session->print;
    }


    print "OK!";
    $tmpFileToBeCompiled->close;

    warn "Connecting finished!\n";
    $session->close;
    $tmp --;
}

$sock_server->close;

----------------------------------------end--------------------------------------------------------
-------------------------------------client.pl--------------------------------------------------------
use warnings;
use strict;

use IO::Socket qw(:DEFAULT);
use File::Copy;
use constant MY_TRAN_PORT => 138000;
use IO::File;

my $host = shift || '127.0.0.1';
my $port = shift || MY_TRAN_PORT;

my $socket = IO::Socket::INET->new("$host:$port") or die $@;

my $fh = IO::File->new("a.c", "r");

my $child = fork();
die "Can't fork: $!\n" unless defined $child;

# if (!$child) {
#     $SIG{CHLD} = sub { exit 0 };
#     userToHost();
#     print "Run userToHost done!\n";

#     $socket->shutdown(1);
#     sleep;
# } else {
#     hostToUser();
#     print "Run hostToUser done! \n";

#     warn "Connection closed by foreign host\n";

# }
userToHost();
unless ($child) {
    hostToUser();
    print "Run hostToUser done! \n";
    warn "Connection closed by foreign host\n";
    $socket->close;

}

sub userToHost {
    while (<$fh>) {
#    print $_;    # for debug
    print $socket $_;
    }
}

sub hostToUser {
    while (<$socket >) {
    print $_;    
    }
}
# copy ("a.c", $socket) or die "Copy failed: $!";
print "Done!";

My OS is Archlinux with perl 5.14.2. I am just trying to write a little program to accomplish a remote comlile. The program just passes a C source file to the server. The server will call gcc to compile the C code and pass the compiler's message. The client can't receive the compiler's message. I have the message in the server.
There is the code:

#!/usr/bin/perl -w
# oj.pl --- alpha


use warnings;
use strict;
use IO::File;
use IO::Socket;

use  constant MY_TRAN_PORT => 138000;
$| = 1;


my $tmpFileToBeCompiled = IO::File->new ("> tmpFile09090989.c") or die "Can't creat this file";

#if (defined $tmpFileToBeCompiled) {
#    print $tmpFileToBeCompiled "argh";         # just for test!
#}
# $fihi->close;

my $port        = shift || MY_TRAN_PORT;

my $sock_server = IO::Socket::INET->new (Listen         => 20,
                                         LocalPort      => $port,
                                         Timeout        => 60,
                                         Reuse          => 1)
    or die "Can't create listening socket: $!\n";

my $tmp = 1;
while ($tmp) {
    next unless my $session = $sock_server->accept;

    my $peer = gethostbyaddr ($session->peeraddr, AF_INET)
        || $session->peerhost;
    warn "Connection from [$peer, $port]\n";

    while (<$session>) {
        print $tmpFileToBeCompiled $_;              # if it works, the filehandle should be changed into tmpFile.  just fixed.
        print $session "test!";

    }

    my @lines = `gcc tmpFile09090989.c 2>&1`;

    foreach ( @lines) {
        print $session  $_ . "test!!!\n";
     #   $session->print;
    }


    print "OK!";
    $tmpFileToBeCompiled->close;

    warn "Connecting finished!\n";
    $session->close;
    $tmp --;
}

$sock_server->close;

----------------------------------------end--------------------------------------------------------
-------------------------------------client.pl--------------------------------------------------------
use warnings;
use strict;

use IO::Socket qw(:DEFAULT);
use File::Copy;
use constant MY_TRAN_PORT => 138000;
use IO::File;

my $host = shift || '127.0.0.1';
my $port = shift || MY_TRAN_PORT;

my $socket = IO::Socket::INET->new("$host:$port") or die $@;

my $fh = IO::File->new("a.c", "r");

my $child = fork();
die "Can't fork: $!\n" unless defined $child;

# if (!$child) {
#     $SIG{CHLD} = sub { exit 0 };
#     userToHost();
#     print "Run userToHost done!\n";

#     $socket->shutdown(1);
#     sleep;
# } else {
#     hostToUser();
#     print "Run hostToUser done! \n";

#     warn "Connection closed by foreign host\n";

# }
userToHost();
unless ($child) {
    hostToUser();
    print "Run hostToUser done! \n";
    warn "Connection closed by foreign host\n";
    $socket->close;

}

sub userToHost {
    while (<$fh>) {
#    print $_;    # for debug
    print $socket $_;
    }
}

sub hostToUser {
    while (<$socket >) {
    print $_;    
    }
}
# copy ("a.c", $socket) or die "Copy failed: $!";
print "Done!";

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绅士风度i 2024-12-22 19:17:16
  1. 您不需要分叉客户端。完全没有。就像themel说的,
  2. 你的客户端代码有错误:<$socket>应该是<$socket>
  3. 你需要通知服务器你已经写入了所有数据并且服务器可以开始编译。否则服务器将永远停留在 while (<$session>) 状态。
    要实现此目的,您可以调用 shutdown($socket, 1) 这意味着您已完成编写。请参阅 perldoc -f shutdown

最终原型(非常粗糙)可以看起来像这样: https://gist.github.com/19b589b8fc8072e3cfff

  1. You don't need to fork in client. At all. Just like themel said
  2. You have error in client code: <$socket > should be <$socket>
  3. You need to notify server that you have written all data and server can start compilation. Otherwise server will stuck at while (<$session>) forever.
    To achieve this you could call shutdown($socket, 1) which means you finished writing. See perldoc -f shutdown

Final prototype (very rough) could look like this: https://gist.github.com/19b589b8fc8072e3cfff

别忘他 2024-12-22 19:17:16

yko 成功了,但我只是建议您的任务将通过从 inetd 运行的 shell 脚本以更容易且更可维护的方式解决。

yko nailed it, but let me just suggest that your task will be solved in a much easier and more maintainable way by a shell script running from inetd.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文