Автор Тема: Проблема с ф-цией recv (Perl). Как завершить скрипт?  (Прочитано 3358 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Evgeny

  • Фанат форума
  • Старожил
  • ****
  • Сообщений: 272
  • +0/-0
  • 0
    • Просмотр профиля
Привет всем.
В моём перл-скрипте я отсылаю udp-пакет, а затем ожидаю ответа. Когда ответ приходит, отсылаю соответствующию информацию пользователю в броузер. Но проблема в том, что при вызове ф-ции recv, скрипт ждёт ответа до тех пор, пока он не прийдёт. И если он не приходит, скрипт висит. Получается каждый раз после такой ситуации остаётся незавершённый процесс? Это ведь очень плохо.
Вопросы такие. Можно ли задать какой-нибудь тайм-аут в ф-ции recv и второй, если на первый нет ответа, можно ли заставить скрипт завершиться самому с выполнением определённой ф-ции по  истечении какого-нибудь времени?
Большое спасибо.

  • Гость
Как я понимаю ты с начала создал и открыл сокет:
типа такого
socket(SOCK, 2,1,6);
bind(SOCK,$this);
connect(SOCK,$that);

а потом читаешь ответ ф-цией recv.

Я читал сокет так:
while(defined ($line=)){
бла-бла-бла
                }
shutdown (SOCK,2);

И если ответа нет- обрабатывался тайм аут и сокет закрывался, при этом скрипт работает дальше.

Если ты юзаешь такой скрипт на халявном хостере, плз, подкинь урл.

Оффлайн Evgeny

  • Фанат форума
  • Старожил
  • ****
  • Сообщений: 272
  • +0/-0
  • 0
    • Просмотр профиля
Нет, я делаю следующим образом:


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). Он позволяет изменить свойства дескриптора файла, в частности, касающиеся применения блокировки и способов обработки некоторых сигналов."

 

Sitemap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28