Forum Webscript.Ru
Программирование => Perl => Тема начата: Evgeny от 29 Января 2002, 16:22:26
-
Привет всем.
В моём перл-скрипте я отсылаю udp-пакет, а затем ожидаю ответа. Когда ответ приходит, отсылаю соответствующию информацию пользователю в броузер. Но проблема в том, что при вызове ф-ции recv, скрипт ждёт ответа до тех пор, пока он не прийдёт. И если он не приходит, скрипт висит. Получается каждый раз после такой ситуации остаётся незавершённый процесс? Это ведь очень плохо.
Вопросы такие. Можно ли задать какой-нибудь тайм-аут в ф-ции recv и второй, если на первый нет ответа, можно ли заставить скрипт завершиться самому с выполнением определённой ф-ции по истечении какого-нибудь времени?
Большое спасибо.
-
Как я понимаю ты с начала создал и открыл сокет:
типа такого
socket(SOCK, 2,1,6);
bind(SOCK,$this);
connect(SOCK,$that);
а потом читаешь ответ ф-цией recv.
Я читал сокет так:
while(defined ($line=)){
бла-бла-бла
}
shutdown (SOCK,2);
И если ответа нет- обрабатывался тайм аут и сокет закрывался, при этом скрипт работает дальше.
Если ты юзаешь такой скрипт на халявном хостере, плз, подкинь урл.
-
Нет, я делаю следующим образом:
socket(S,PF_INET,SOCK_DGRAM,getprotobyname("udp")) || die "socket: $!";
$ipaddr=inet_aton($zielIP);
$portaddr=sockaddr_in($port,$ipaddr);
send(S,$msg,0,$portaddr) == length($msg) || die "cannot send to $ip($port): $!";
$portaddr=recv(S,$msg,350,0) or die "recv: $!";
($portno,$ipaddr)=sockaddr_in($portaddr);
$host=gethostbyaddr($ipaddr,AF_INET);
Так вот, если никакого ответа нет, то скрипт виснет на строке:
$portaddr=recv(S,$msg,350,0) or die "recv: $!";
Как этого избежать?
lalex , скрипт не на халявном хостере.
-
На этой строке виснуть, по идее, не должен. Потому как ему плевать, получит он что-нибудь или нет :)
В perldoc perlipc есть неплохой пример про запросы к time-server. Может там найдете решение?
-
Кажись я знаю как решить твою проблему.
Вчера прочитал в книжке по линуху. Есть такое понятие "блокирующие и неблокирующие дескрипторы".
В твоем случае имеется блокирующий дескриптор. Т.е. функция recv() будет работать до тех пор пока в сокет не поступит порция инфы.
"...Неблокирующим называют такой ввод/вывод, где операция возвращает код ошибки или состояния еще до полного своего завершения."
Для того чтобы сделать сокет(дескриптор) неблокирующим надо использовать модуль Fcntl.
Пример:
#!/usr/bin/perl
use socket;
use Fcntl;
....
socket(SOCK,..,..,..);
bind (SOCK,...);
fcntl (SOCK, &F_SETFL,O_NONBLOCL);
recv (SOCK,..,..,..)
.....
"...модуль Fcntl предоставляет интерфейс к системному вызову fcntl(2). Он позволяет изменить свойства дескриптора файла, в частности, касающиеся применения блокировки и способов обработки некоторых сигналов."