Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   PHP, PERL, MySQL, JavaScript (https://forum.antichat.xyz/forumdisplay.php?f=37)
-   -   Perl многопоточночть (https://forum.antichat.xyz/showthread.php?t=89332)

zer0ska 27.10.2008 20:59

Perl многопоточночть
 
Подскажите как скрипт такого вида cделать многопоточным или дайте ссылки на нормальные мануалы по много поточности perl.

Код:

#!/usr/bin/perl
use Socket;

%ipr = ('192.168.0.1' => '1',
        '192.168.0.2' => '2',
        '192.168.0.3' => '3');


$p='135';


foreach $ip (keys %ipr){

        socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));

        $iaddr = inet_aton($ip);
        $paddr = sockaddr_in($p, $iaddr);
        if(connect(SOCK, $paddr)) {
                print $ip." [connect]\r\n";
        }
        else {
                print $ip." [error]\r\n";
        }

        # send (SOCK, "", 0);
        close(SOCK);
        $i++;
}


Spyder 27.10.2008 21:07

Код:

#!/usr/bin/perl
use Socket;
use threads;
use threads::shared;
my @ipr : shared;

$thr = 2;    # потоки
@ipr = ('192.168.0.1', '192.168.0.2', '192.168.0.3');



$p='135';

for(0..$thr)
{
$trl[$_] = threads->create(\&Prog, $_);
}
for(0..$thr)
{
$trl[$_]->join;
}

sub Prog {

while (@ipr){

        $ip = shift;
        socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));

        $iaddr = inet_aton($ip);
        $paddr = sockaddr_in($p, $iaddr);
        if(connect(SOCK, $paddr)) {
                print $ip." [connect]\r\n";
        }
        else {
                print $ip." [error]\r\n";
        }

        # send (SOCK, "", 0);
        close(SOCK);
        $i++;
}
}

Вроде так, только я там заюзал через массив, а не через хеш

Spyder 27.10.2008 21:23

spyder@local:~> perl tt.pl
0 [error]
1 [error]
Thread 1 terminated abnormally: Bad arg length for Socket::pack_sockaddr_in, length is 0, should be 4 at /usr/lib/perl5/5.10.0/i586-linux-thread-multi/Socket.pm line 386.
Thread 2 terminated abnormally: Bad arg length for Socket::pack_sockaddr_in, length is 0, should be 4 at /usr/lib/perl5/5.10.0/i586-linux-thread-multi/Socket.pm line 386.
2 [error]
Thread 3 terminated abnormally: Bad arg length for Socket::pack_sockaddr_in, length is 0, should be 4 at /usr/lib/perl5/5.10.0/i586-linux-thread-multi/Socket.pm line 386.

ошибки вываливаются, я думаю надо поставить проверку на не пустое значение $ip что бы их небыло

fry 28.10.2008 01:54

То что ты делаешь наверное можно сделать простым форком.

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

Теперь вот я что прочитал
http://perldoc.perl.org/threads.html

Как я понял, создаёться копия перла на каждый поток. Переменый не являються общими. И для скрипта это выглядит как форк.

Вывод использовать форк проще всего или взять язык который разработан для правильной работы в потоками (умеет синхронизировать код)

zer0ska 28.10.2008 17:26

!
 
Вот что я своими силама накодил поправте если где ошибки )
Код:

#!/usr/bin/perl
use threads;
use Socket;

%ipr = ('192.168.0.1' => '1',
        '192.168.0.2' => '2',
        '192.168.0.3' => '3');


$p='135';

$i =0;

foreach $ip (keys %ipr){

        socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
        $thr[$i]=threads->create(\&test_connect, $ip, $p);

        $iaddr = inet_aton($ip);
        $paddr = sockaddr_in($p, $iaddr);
        close(SOCK);
        $i++;
}

sub test_connect {
        $iaddr = inet_aton($ip);
        $paddr = sockaddr_in($p, $iaddr);
        if(connect(SOCK, $paddr)) {
                print $ip." [connect]\r\n";

                return  $ip;

        }
        else {
                print $ip." [error]\r\n";
                return $ip;
        }

        # send (SOCK, "", 0);
        return;
}


Kaimi 28.10.2008 18:07

Код:

use warnings;
use strict;
use Socket;
use threads;
use threads::shared;

my @trl;
my $p = '135';
my $threads = 2;
my @ipr : shared = qw(192.168.1.1 192.168.1.2 192.168.1.3);

for(0..$threads) {$trl[$_] = threads->create(\&check, $_);}
for(@trl) { $_->join; }

sub check {
my $ip;
while(@ipr) {
        {lock(@ipr); $ip = shift(@ipr);}
        socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
        my $iaddr = inet_aton($ip);
        my $paddr = sockaddr_in($p, $iaddr);
        connect(SOCK, $paddr) ? (print "$ip [connect]\r\n") : (print "$ip [error]\r\n");
        close(SOCK);
        }
}


biophreak 28.10.2008 18:07

use warnings 'all';
use strict;
use diagnostics;
и правь ;)
PS: И не лучше-ли сделать цикл вне функции?

Spyder 28.10.2008 18:45

fry, юзать форки для этой задачи не имеет смысла, куда проще и быстрее сделать всё с потоками

zer0ska 30.10.2008 16:47

!
 
Вот так сказать последняя версия :-)
Код:

#!/usr/bin/perl
use threads;
use Socket;

$p  = '139';
$sip = '192.168.0.';

for(1..255) {
        $ip = '192.168.0.'.$_;
        $thr[$_]=threads->create(\&conn, $ip, $p, SOCK)->join;
       
}
sub conn {
        socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
        $iaddr = inet_aton($ip);
        $paddr = sockaddr_in($p, $iaddr);
       
        if(connect(SOCK, $paddr)) {
                print $ip."\r\n";
                close(SOCK);
                return;

        }
        else {
                close(SOCK);
                return;
        }

        # send (SOCK, "", 0);
        return;
}

посоветуйте как по грамотней распределять потоки потому что диапазон может быть не только от 0 до 255 но и больше а создавать 1000 потоков имхо не есть гуд )
Как лучше создовать сокет внутри фнкции или создать один а в функции юзать только connect ?

zythar 30.10.2008 16:58

ну дак ты попробуй и тем и другим способом. посмари в каком случае быстрее с помощью time-a и сделай так как тебе выгодно.


Время: 00:33