PDA

Просмотр полной версии : Perl многопоточночть


zer0ska
27.10.2008, 20:59
Подскажите как скрипт такого вида 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 и сделай так как тебе выгодно.

zer0ska
30.10.2008, 17:19
мне важна не только скорость но и нагрузка на сервер
конечно это можно определить и опытным путём :-)

Spyder
30.10.2008, 18:11
ипы в массив и через шифт их извекаешь в каждом потоке, посмотре мой первый пост

nerezus
30.10.2008, 22:44
То что ты делаешь наверное можно сделать простым форком.

Зачем какать, если можно выблевывать все через рот?

Потому что:
1. Какать через попу легче.
2. У бодьшинства людей процесс выблевывания сопровождается неприятными ощущениями и не всегда протекает гладно.
3. Выблевывание менее гигиенично.
4. После выблевывания недостаточно вытереть рот - придется выполнять специальные процедуры для прочистки.
5. Выблевывание сопровождается потерей соли в организме.
6. Какать - более гибко. Какание происходит по типу логичный queue, в то время как для выблевывания приходится юзать неуместный stack и верхние элементы его будут необработаны.

Spyder
30.10.2008, 23:41
5. Выблевывание сопровождается потерей соли в организме.

спасибо, не знал

KSURi
31.10.2008, 00:22
Но кстати после выблевывания обычно полегче становится

biophreak
31.10.2008, 10:40
Чем после выкакивания? :) Не факт :)