0

Unix ソケットを介して単純なエコー クライアント/サーバーを実装しようとしています。(私の最終的な目標は JSON データを交換することですが、この例は簡単にするためです)。クライアント プロセスが 2 回目にソケットに出力しようとすると、ブラック ホールに消えてしまう理由がわかりません。

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";
}

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";

期待される出力:

> ./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 に答える