|
|
ru.perl- RU.PERL ---------------------------------------------------------------------- From : Andrey Chernomyrdin 2:5020/400 13 Oct 2001 00:02:04 To : All Subject : Unix socket timeout... -------------------------------------------------------------------------------- Hi! Вот тут вот столкнулся с проблемой при написании маленькой програмки которая между клиентом и сервером использует UNIX сокеты. то есть если следать на сервере: $socket->print( "Data1...\n" ); $socket->print( "Data2...\n" ); а в клиенте: $socket->getline; # читает Data1... $socket->getline; # виснет на таймауте. Hебольшая программа (см. ниже) иллюстрирует это: запускаем сервер: - -- $ ./usample.pl --server Client connect << 220 Server ready >> add one << . Client close Client connect << 220 Server ready >> add two << . Client close Client connect << 220 Server ready >> list << 214 one << 214 two << . Client close - -- и соответствующие вызовы с клиентской стороны: - -- $ ./usample.pl --add one >> 220 Server ready << add one >> . $ ./usample.pl --add two >> 220 Server ready << add two >> . $ ./usample.pl --list >> 220 Server ready << list >> 214 one read timeout $ - -- то есть сервер работает вроде-бы как нужно, а вот клиент более чем одной строчки вводить не хочет ;-) Если добавть на сервере задержку после вывода каждой строки (0.1 .. 0.25 сек) то все вроде-бы как оживает, но IMHO это как-то неправильно. Может-быть кто-нибудь что-нибудь присоветует на данную тему, может какой FM почитать ? Заранее благодарен. Программа: - -- #!/usr/bin/perl -w package usample; use strict; use IO::Socket; use IO::Select; use Getopt::Long; my $timeout = 0.25; my @List = (); &main; 1; sub main { my $sock_name = '/tmp/usample.sock'; my %opt; GetOptions( 'server' => \$opt{server}, 'list' => \$opt{list}, 'add=s' => \$opt{add}, ); if( $opt{server} ) { do_server( $sock_name ); } else { if( $opt{list} ) { do_client( $sock_name, 'list' ); } elsif( $opt{add} ) { do_client( $sock_name, 'add', $opt{add} ); } } } sub do_server { my $sock_name = shift; my $stop = 0; my $banner = "220 Server ready\n"; my ( $sock, $sel, @ready, $fh, $s ); $sock = IO::Socket::UNIX->new( Local => $sock_name, Type => SOCK_STREAM, Listen => 5 ) if( not -S $sock_name ); if( not defined $sock ) { print "Server already runing: $!"; exit 1; } $sock->autoflush( 1 ); $SIG{INT} = $SIG{KILL} = sub { $stop = 1; }; $sel = IO::Select->new; $sel->add( $sock ); while( not $stop ) { while( @ready = $sel->can_read() ) { foreach $fh ( @ready ) { if( $fh == $sock ) { print "Client connect\n"; $s = $sock->accept; $s->autoflush( 1 ); if( write_ready( $s, $timeout ) ) { $s->print( $banner ); print '<< ', $banner; } $sel->add( $s ); } else { if( process_client( $fh ) ) { $sel->remove( $fh ); $fh->close; } } } } } $sock->close; undef $sock; unlink( $sock_name ) if( -S $sock_name ); } sub process_client( $fh ) { my $sock = shift; my $rc = 0; my ( $line, $cmd, ); if( $line = $sock->getline ) { print '>> ', $line; if( $line =~ /^list$/ ) { local $_; foreach ( @List ) { if( write_ready( $sock, $timeout ) ) { $sock->print( "214 $_\n" ); print '<< ', "214 $_\n"; # select( undef, undef, undef, $timeout ); # задержка после вывода... } } } elsif( $line =~ /^add (.*)$/ ) { $_ = $1; chomp; push( @List, $_ ); } if( write_ready( $sock, $timeout ) ) { $sock->print( ".\n" ); print '<< ', ".\n"; } } else { $rc = 1; print "Client close\n"; } return $rc; } sub do_client { my $sock_name = shift; my ( $cmd, $arg ) = ( shift, shift ); my $sock = undef; my $stop = 0; $sock = IO::Socket::UNIX->new( Peer => $sock_name, Type => SOCK_STREAM ) if( -S $sock_name ); if( not defined $sock ) { print "Server not found: $!"; exit 1; } $sock->autoflush( 1 ); if( read_ready( $sock, $timeout ) ) { print '>> ', $sock->getline; } if( $cmd eq 'add' ) { $sock->print( "add $arg\n" ); print '<< ', "add $arg\n"; } elsif( $cmd eq 'list' ) { $sock->print( "list\n" ); print '<< ', "list\n"; } else { $stop = 1; } while( not $stop ) { if( read_ready( $sock, $timeout ) ) { my $line = $sock->getline; print '>> ', $line; chomp $line; $stop = 1 if( $line eq '.' ); } else { print "read timeout\n"; $stop = 1; } } $sock->close; undef $sock; } sub vector { my ( $fileno, $v ) = ( shift, '' ); vec( $v, $fileno, 1 ) = 1; return $v; } sub write_ready { my ( $fh, $t ) = ( shift, shift ); return select( undef, vector( $fh->fileno ), undef, $t ); } sub read_ready { my ( $fh, $t ) = ( shift, shift ); return select( vector( $fh->fileno ), undef, undef, $t ); } - -- -- With Best, Andrey --- ifmail v.2.15dev5 * Origin: X-Com Online (2:5020/400) Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /ru.perl/642658b0b6e3.html, оценка из 5, голосов 10
|