这个IO :: Socket :: UNIX示例有什么问题?

1in*_*ion 0 perl io-socket

我试图通过Unix套接字实现一个简单的echo客户端/服务器.(我的最终目标是交换JSON数据,但这个例子是为了简单起见).我不知道为什么客户端进程第二次尝试打印到套接字时会消失在黑洞中.

server.pl:

use IO::Socket::UNIX;

my $socket_path = '/tmp/mysocket';
unlink $socket_path if -e $socket_path;

my $socket = IO::Socket::UNIX->new(
    Local  => $socket_path,
    Type   => SOCK_STREAM,
    Listen => SOMAXCONN,
);

die "Can't create socket: $!" unless $socket;

while (1) {
    next unless my $connection = $socket->accept;
    chomp( my $line = <$connection> );
    print $connection "$line\n";
}
Run Code Online (Sandbox Code Playgroud)

client.pl:

use IO::Socket::UNIX;

my $socket = IO::Socket::UNIX->new(
    Type => SOCK_STREAM,
    Peer => '/tmp/mysocket',
);

die "Can't create socket: $!" unless $socket;

my $line;

print $socket "one\n";
chomp( $line = <$socket> );
say $line;

print $socket "two\n";
chomp( $line = <$socket> );
say $line;

say "three";
Run Code Online (Sandbox Code Playgroud)

预期产量:

> ./client.pl
> one
> two
> three
Run Code Online (Sandbox Code Playgroud)

实际产量:

> ./client.pl
> one
Run Code Online (Sandbox Code Playgroud)

mob*_*mob 6

你把这个$socket->accept电话放在你的while循环中.在服务器建立连接并从客户端接收一些输入之后,接下来要做的就是建立新连接.

accept呼叫移到while循环外部

my $connection = $socket->accept;
$connection->autoflush(1);
while (my $line = <$connection> ) {
    chomp($line);
    print $connection "$line\n";
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您确实想接受多个连接,

while (1) {
    next unless my $connection = $socket->accept;
    $connection->autoflush(1);
    while (my $line = <$connection>) {
        chomp($line);
        print $connection "$line\n";
    }
}
Run Code Online (Sandbox Code Playgroud)

您当前的解决方案也可能"遭受缓冲",因此服务器和客户端都应该设置autoflush(1)其套接字处理程序.

现在要处理同时连接,服务器通常会fork在获得连接后调用,并在子进程中处理该连接.

while (1) {
    my $connection = $socket->accept;
    if (fork() == 0) {
        $connection->autoflush(1);
        while (my $line = <$connection>) {
            chomp($line);
            print $connection "$line\n";
        }
        close $connection;
        exit;
    }
}
Run Code Online (Sandbox Code Playgroud)