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


Автор: Linco 22.12.2005, 16:43
Здравствуйте! Значит имеется следующая ситуация, есть необходимость в создании клиента и сервера, которые должны работать в режиме запрос-ответ т.е.
Клиент: запрос
Сервер: выбор из БД, ответ
Клиент: обработка данных, ответ новыми данными
Сервер: добавление данных в БД, закрытие
Я не специалист в перле в итоге родилось нечто следующее:
сервер:
Код

   my $server = IO::Socket::INET->new(
                                Proto     => 'tcp',
                                LocalPort => $server_port,
                                Type      => SOCK_STREAM,
                                Reuse     => 1,
                                Listen    => 10 );   # or SOMAXCONN
     if(!$server)
    {
        print("Couldn't be a tcp server on port $server_port : $@\n");
        exit;
    }
    else
    {
        print("Server created on port: $server_port $@\n");
    }
    $server->autoflush(1);
    while ($client = $server->accept())
    {
        $server->autoflush(1);
        $client->autoflush(1);
        print $client "Connection accepted";
        print ('Connection from ',$client->peerhost(),':',$client->peerport()," accepted. \n");
        while (<$client>) {
            if ($_ = 'stats'){
             statsquery();//функция делает запрос к БД, получает данные и пишет их в массив @dblist как CSV, она нам не интересна :)
             last;
            }#if
        }#while
        print "Sended \n @dblist";
        print $client @dblist or die "Cannot send"; 
    }
    $server->close;
    print("Server closed");
}

Клиент:
Код

    my $client = IO::Socket::INET->new(Proto     => "tcp",
                                        PeerAddr  => $server_addr,
                                        PeerPort  => $server_port,
                                        Type=> SOCK_STREAM)               
     or die "Cannot connect to host: $server_addr:$server_port \n";
    $client->autoflush(1);
    $client->recv(my $text,128);
    print "$text\n";
     $client->send("stats") or die "Not sended: $!\n";
   
    $client->recv($buf,1024);//если этого нет то на сервере все проходит, только клиент естественно данные не получает
    print $buf;
    close ($client);
    print "Client closed";
}

если есть сервер останавливается на if ($_ = 'stats')
Я так понимаю что срабатывает блокировка, и почему-то даже посланная 'stats' до сервера не доходит. Как это обойти не представляю. Пробовад и с Select и c FORK но видимо не так пробовал. Клиент будет один и обмен данными будет строго последовательный так что не представляю почему он блокирует оба конца smile
может подскажет кто?

Автор: stan777 12.4.2007, 10:44
Blocking => 0,                   # This line is very important
Как написано в спане это вроде должно отключить блокировку сокета. Хотя сам еще не пытался вот только пробую.

Автор: KSURi 12.4.2007, 12:22
Не понимаю при чем тут Nonblocking?

Когда ты делаешь recv у сокета, он "блокируется", те управление в основную программу не возвращается, пока туда не придёт хотя-бы 1 байт. А неблокирующий режим позволят не ждать завершения операции, те управление сразу вернётся в главную программу. Тоже самое относится к вызовам send, write и тд.

Добавлено через 14 минут и 20 секунд
c.pl:
Код

#!perl -w

use strict;
use warnings;
use IO::Socket;

my $c = IO::Socket::INET->new(PeerAddr => '172.22.6.236',
                              PeerPort => 6236,
                              Proto => 'tcp') || die;
$c->autoflush(1);

my $in;
$c->recv($in, 20) || die 'no handshake';
print $in, "\n";
$c->send('stats');
$c->recv($in, 1024) || die 'no answer';
print $in, "\n";

$c->shutdown(0);


s.pl:
Код

#!perl -w

use strict;
use warnings;
use IO::Socket;

my $s = IO::Socket::INET->new(LocalAddr => '172.22.6.236',
                              LocalPort => 6236,
                              Proto => 'tcp',
                              Listen => 1) || die;
$s->autoflush(1);

while(1)
{
    next unless my $c = $s->accept;
    $c->send('Connection accepted');
    my $in;
    $c->recv($in,5) || last;
    print $in, "\n";
    $in eq 'stats' || last;
    
    # do some actions here
    $c->send('Ok, test was successful');
}

$s->shutdown(0);

Автор: stan777 12.4.2007, 17:02
Цитата(KSURi @ 12.4.2007,  12:22)
Не понимаю при чем тут Nonblocking?

Ну как бы и не причем, притом что у него один клиент к серверу конектится smile.  Вот если бы клиент имел бы больше одного конекта и хотел бы из них одновременно качать и сохранять, то думаю бы потребовались сокеты без блокирования. 

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