Главная страница


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)
 
 

Вернуться к списку тем, сортированных по: возрастание даты  уменьшение даты  тема  автор 

 Тема:    Автор:    Дата:  
 Unix socket timeout...   Andrey Chernomyrdin   13 Oct 2001 00:02:04 
 Re: Unix socket timeout...   Vladimir Podgorny   13 Oct 2001 11:22:20 
 Re: Unix socket timeout...   Pavel Ammosov   13 Oct 2001 18:36:07 
 Re: Unix socket timeout...   Vladimir Podgorny   13 Oct 2001 18:52:25 
 Re: Unix socket timeout...   yurik shestakov   13 Oct 2001 13:00:14 
Архивное /ru.perl/642658b0b6e3.html, оценка 2 из 5, голосов 10
Яндекс.Метрика
Valid HTML 4.01 Transitional