Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Системное программирование > loop в клиент-серверное приложении


Автор: Ky6uk 15.7.2008, 00:24
В сети имеется некий сервер. Необходимо написать клиент для работы с этим сервером. На данный момент у меня имеется набор последовательно выполняющихся функций для работы с сервером. То есть в первой функции инициируется соединение с сервером, во второй читается пакет из сокета, в третьей обрабатывается пакет и отсылается на сервер, в четвертой опять читается и так далее, до конечного результата.
По понятным причинам появилась необходимость организовать цикл, в котором будут читаться пакеты из сокета, обрабатываться и, в зависимости от результата, будет выполняться тот или иной handler, вызывающий закрепленную за ним функцию. Эта функция будет обрабатывать данные и отсылать ответ на сервер. Ну и так далее.

Хотелось бы получить советы от уже сталкивавшихся с данной задачей. Как это можно удачнее организовать? У меня есть идеи насчет помещения в цикл recv() из модуля Socket. Но как такой цикл будет вести себя в режиме ожидания данных? Как будут запускаться функции в зависимости от результата, возвращаемого recv()? Удачная ли идея? Ну и много подобных вопросов, так как ни разу не писал клиентское приложение, работающее в реальном времени.

Заранее спасибо.

Автор: KSURi 15.7.2008, 01:33
В простейшем случае это будет выглядеть примерно так:
Код

print "session started\n";
while(my $buffer = <$sock>) {
  process_input_packet();
  send_output_packet();
  last if $condition;
}
print "session stopped\n"


ЗЫ: есть замечательная книга Линкольна Д. Штайна "Сетевое программирование на Perl", советую обратиться к ней за конкретными примерами

Автор: tolkien 15.7.2008, 04:31
Код

my $SOCK = undef;

$SOCK = set_connect(host, port) or die "can't set connect to $host $port";

while(1)
{
   if (is_data($SOCK))
  {   
      my $data = '';
      get_data($SOCK, \$data);
      #распарсить $data
      #что нибудь сделать с $data
   }
}

sub is_data
{
  my ($SOCK) = @_;
  my $rin = '';
  my $rout = 0;
  vec($rin, fileno($SOCK), 1) = 1;
  my $nfound = select($rout=$rin, undef, undef, .8);     
  return $nfound > 0;
}

sub set_connect
{
  my ($host, $port) = @_;
  my $proto = getprotobyname('tcp');
  local *S;
  my $handle = *S;
  socket($handle, PF_INET, SOCK_STREAM, $proto);
  my $sin = sockaddr_in($port,inet_aton($host));
  connect($handle,$sin) || return undef;
  my $old_fh = select($handle); 
  $| = 1;                # don't buffer output
  select($old_fh);
  return $handle;
}

#$data - ref
sub get_data
{
  my ($handle, $data, $size) = @_;
  my $len = 512;
  my $rv = 1;
 
  while (1)
  { 
    my $buf = '';
    my $r = sysread($handle, $buf, $len);

    if (!defined($r))
    {
      $rv = undef;
      last;
    }
    
    ${$data} .= $buf;
    
    if ($size && length(${$data}) >= $size)
    {
      last;
    }
    elsif ($r == 0) 
    {
      last;
    }
    elsif ($r < $len)
    {
      my $rin = '';
      my $rout = '';
      vec($rin, fileno($handle), 1) = 1;  
      my $nfound = select($rout=$rin, undef, undef, .2);
      last if ($nfound <= 0);
    }
  }

  return $rv;
} 
     

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)