0

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

服务器.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";
}

客户端.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";

预期输出:

> ./client.pl
> one
> two
> three

实际输出:

> ./client.pl
> one
4

2 回答 2

6

你把$socket->accept调用放在你的while循环中。在您的服务器建立连接并从客户端接收到一些输入后,它要做的下一件事就是建立一个新连接。

accept呼叫移到while循环外

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

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

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

您当前的解决方案也可能会“遭受缓冲”,因此服务器和客户端都应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;
    }
}
于 2013-02-19T00:17:06.203 回答
3

对于任何人来说,一个完整的双向示例:

服务器:

#! /usr/bin/perl -w

use strict;

use IO::Socket::UNIX qw( SOCK_STREAM SOMAXCONN );

my $SOCK_PATH = '/tmp/test.sock';
unlink($SOCK_PATH) if -e $SOCK_PATH;

my $server = IO::Socket::UNIX->new(
   Type => SOCK_STREAM(),
    Local => $SOCK_PATH,
   Listen => SOMAXCONN,
)
   or die("Can't create server socket: $!\n");

while (1) {
    my $connection = $server->accept;
    if (fork() == 0) {
        print "** New connection received **\n";
        $connection->autoflush(1);
        my $count = 1;
        while (my $line = <$connection>) {
            if ($line){
                chomp($line);
                $connection->print($count . ' -> ' . $line . "\n"); # Sent response back to client, \n terminates
                print "Received and replied to $count '$line'\n";
                $count++;
            }
        }
        close $connection;
        exit;
    }
}

客户:

#!/usr/bin/perl -w

use strict;

use IO::Socket::UNIX qw( SOCK_STREAM );

my $SOCK_PATH = '/tmp/test.sock';

my $client = IO::Socket::UNIX->new(
   Type => SOCK_STREAM(),
   Peer => $SOCK_PATH
)
   or die("Can't connect to server: $!\n");

$client->autoflush(1);


## Listen for replies
if (fork() == 0) {
    while (my $line = <$client>) {
        if ($line){
            chomp($line);
            print("Recv: '" . $line . "'\n");
        }
    }
}

## Send something
for my $itm ('Alpha','Beta','Gamma','Delta'){
    print("Send: " . $itm . "\n");
    print($client $itm . "\n") or warn("Can't send: $!\n"); # send to server, \n terminates
}

print "** Client Finished **\n";
于 2017-11-08T07:47:35.960 回答