Perl: обработка тайм-аута получения пакета UDP с помощью процессов

Сейчас я разрабатываю графический интерфейс для своей сенсорной сети с помощью Perl-TK. Основная проблема заключается в том, что иногда моя сеть с низким энергопотреблением страдает от потери пакетов. В этом случае моя программа Perl застревает, например, в рукопожатии. Рукопожатия выполняются в разных процессах. Я хотел бы кричать для пользователя, когда пакет не получен, и закрыть поток

Есть ли решения для реализации любого тайм-аута для процессов уничтожения?

редактировать: он работает с основным циклом. Но в конкретном процессе не работает, программа останавливается и терминал сбрасывает "Будильник". Половинчатый результат:

#!usr/bin/perl
use Thread;
use IO::Socket::IP;
use Net::IP;
use Time::Out qw(timeout);
use warnings;

$conn_timeout = 2;
$th1=Thread->create(\&thr1);
while(1)
    {
        sleep(2);
        print"main proc\n";
    } 
sub  thr1{
 print "thread started\n";
        $temp = '2001:4428:29a::280:e103:1:57a8';
        $ip=Net::IP::ip_expand_address($temp, 6);
        $tempsock = IO::Socket::IP ->new(
                PeerAddr => $ip,
                PeerPort => '52525',
                Proto    => 'udp',
        ) or die "Cannot construct socket, IP address: $ip - error message: - $@";
        print "Socket opened successfully for $ip on port 52525\n";
        $SIG{ALRM} = sub {print "detaching...\n";thr1->detach(); }; # NB: \n required
        alarm $conn_timeout;
        $tempsock ->send("asdasd");
        $tempsock->recv($tempdata, 16);
        alarm 0;
}

редактировать 2: Невозможно использовать сигнал тревоги в потоках... Поэтому я должен измерить время ожидания в связь.


person mkiss    schedule 28.11.2013    source источник


Ответы (1)


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

eval {
    local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
    alarm $timeout;
    $nread = sysread SOCKET, $buffer, $size;
    alarm 0;
};
if ($@) {
    print ("Timeout occurred") unless $@ eq "alarm\n";   # propagate unexpected errors
    # timed out
}
else {
    # didn't
}
person Noam Rathaus    schedule 28.11.2013
comment
Я вставил это, и оно не кричит:code $tempsock -›send(asdasd); local $SIG{ALRM} = sub { тревога\n }; # NB: \n требуемый сигнал тревоги $conn_timeout; $tempsock-›recv($tempdata, 16); if ($@) { print (Время ожидания истекло), если только $@ eq alarm\n; # распространять непредвиденные ошибки # истекло время ожидания } - person mkiss; 28.11.2013
comment
какие? не понял, перефразируй - person Noam Rathaus; 28.11.2013
comment
Извините, я новичок, и я хотел бы записать свой код здесь, как я могу вставить отформатированный исходный код? :) Как вы видите выше... - person mkiss; 28.11.2013
comment
@Nolex: в комментариях вы можете использовать обратные кавычки для форматирования like this, но не для новых строк. Лучше всего было бы отредактировать ваши вопросы с новой информацией. В «Вопросах и ответах» вы можете отформатировать код, как это сделал narathaus, сделав отступ в 4 пробела. Также есть кнопка, позволяющая сделать это сразу для вставленных материалов. - person DeVadder; 28.11.2013
comment
@nrathaus Он отлично работает в основном цикле. Но когда я использую в конкретном процессе, когда время истекло, он умирает, но не умирает в сабе. Терминал сбрасывает будильник и программа останавливается. - person mkiss; 28.11.2013
comment
Возможно, где-то есть какой-то другой обработчик сигналов ИЛИ вы порождаете процесс, и сигнал идет к родителю? - person Noam Rathaus; 28.11.2013
comment
О, я вижу, что вы написали, попробуйте IO::Socket::Timeout - metacpan.org /pod/IO::Socket::Timeout - person Noam Rathaus; 28.11.2013