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

时间:2013-02-19 00:01:52

标签: 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";
}

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

2 个答案:

答案 0 :(得分: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;
    }
}

答案 1 :(得分:0)

完整的双向示例,适合所有人:

服务器:

#! /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";