Xpoint
   [напомнить пароль]

Многопоточность и сокеты - мешает задержка в fsockopen

Метки: [без меток]
2009-02-18 13:30:50 [обр] ice[досье]

Здравствуйте уважаемые!
Передо мной стоит тривиальная :) задача многопоточной проверки списка прокси-серверов на анонимность и тайм-аут. Задача решена мной посредством использования неблокирующих сокетов.
Я попробовал из своего готового кода убрать все обработчики ошибок и прочий "мусор" типа записей в лог-файлы, но даже в таком виде он весьма трудночитаем. Поэтому, если позволите, объясню алгоритм "на пальцах", тем более, что не в алгоритме как таковом дело.
Вот алгоритм в максимально сжатом виде:
Я последовательно открываю 20 сокетов функцией fsockopen, но после каждого такого открытия я запускаю цикл опроса уже открытых сокетов, и, если какой-то сокет удалось полностью прочесть, я вычисляю тайм-аут и проверяю анонимность.
Но есть проблема связанная с функцией fsockopen. Дело в том, что в случае недоступного или сильно заторможенного прокси-сервера, fsockopen естественно останавливает выполнение скрипта на время своего тайм-аута. Когда тайм-аут истекает и управление переходит от fsockopen к циклу обработки открытых сокетов, я уже не могу с достаточной точностью вычислить тайм-аут для сокетов, в которых уже лежит ответ от других прокси-серверов - скрипт спал на протяжение тайм-аута fsockopen и когда конкретно в других сокетах появились ответы мне уже не узнать. Ситуация осложняется еще и тем, что тайм-аут функции fsockopen я должен выставлять большой (т.к. мне нужны прокси-серверы с тайм-аутом до 20 секунд), а тайм-ауты самих прокси-серверов я хочу измерять с достаточно высокой точностью (до десятых долей секунды).

Соответственно, у меня возник вопрос, который я не смог решить ни поиском по всему интернету, ни поиском по этому форуму. Можно ли инициировать процесс открытия сокета таким образом, чтобы процесс установления соединения (если он занимает много времени) не останавливал исполнение скрипта, а происходил как бы фоном?
Надеюсь, у меня получилось понятно сформулировать мою проблему.
Заранее благодарю за ответ.
С Уважением, Алексей.

спустя 24 минуты [обр] MiRacLe(47/77)[досье]
спустя 41 минуту [обр] ice[досье]
MiRacLe[досье], спасибо за ответ. Вы предлагаете перейти от использования сокетов к применению функций потоков? С потоковыми функциями я не работал. Если мою проблему не решить сокетами, придется изучать работу с потоками. Неужели, действительно, работая с сокетами никак не избавиться от описанной проблемы вынужденного простоя скрипта? Может, все же есть какие-нибудь методы (например, используя арсенал низкоуровневого программирования сокетов, а не функцию fsockopen)?
спустя 21 минуту [обр] MiRacLe(47/77)[досье]
вы наверное тёплое с мягким путаете "stream" это не "thread"
спустя 5 минут [обр] ice[досье]
MiRacLe[досье], да прошу прощения, имел в виду stream, говоря про потоки. Насколько я понимаю, stream-функции и непосредственная работа с сокетами (fsockopen и т.п.) это две большие разницы, как говорят в Одессе.
спустя 11 часов [обр] Василий Свиридов(53/175)[досье]
Мне кажется, что задачи такого рода плавно уходят от PHP. Лучше такие вещи писать скажем на С, используя select или fork. В PHP кстати можно попробовать с pcntl_fork. Или-же просто создавать процессы проверяльщики не дожидаясь их завершения и мониторить результат выполнения через AJAX.
спустя 6 часов [обр] MiRacLe(47/77)[досье]
stream_select — Runs the equivalent of the select() system call on the given arrays of streams...
PHP partially supports "Process Control Functions" that were, early in PHP V4's history, a preferred way to program concurrency.
 With PHP V5, stream_select and related functions supplant PCNTL for the concurrency described in this article.
спустя 7 часов [обр] ice[досье]

Василий Свиридов[досье]
>Мне кажется, что задачи такого рода плавно уходят от PHP
Да, я знаю. Но мне необходимо решить задачу в рамках РНР. Да и на С я, судя по всему, столкнусь с похожей проблемой при использовании connect() (правда, решение этой проблемы для С уже описано, см. ниже).

MiRacLe[досье], цитаты отличные. Я ознакомился со Streams-функционалом. Действительно, удобно. Спасибо за наводку.

Но, как я понял, у меня проблема не с обработкой/сканированием уже открытых сокетов, а с самим процессом первоначального установления соединения с удаленной машиной. Вот здесь хорошо описана проблема, правда не для РНР. Т.е. при вызове stream_socket_client (если использовать Streams-функционал) я так же столкнусь с описанной в первом посте сложностью - необходимостью ждать истечения тайм-аута. Нет ли в РНР возможности установить неблокирующий режим работы с сокетами еще до установки соединения, как это описано в статье по приведенной ссылке?

спустя 7 часов [обр] Василий Свиридов(53/175)[досье]
ice[досье]Я думаю, что вам стоит попробовать разбить функционал на несколько кусков:
  • Кусок, который инициирует проверку нескольких адресов (запустил и забыл не дожидаясь завершения).
  • Кусок, выполняющий проверку (тот, который может работать долго, т.к. он не интерактивен).
  • Кусок, мониторящий результат отработавших проверяльщиков (аякс или незакрывающийся сокет. либо мониторить файлы через PHP_FAM, либо через pcntl_kill c пользовательскими сигналами от проверяльщика) и обновляющий страницу по мере поступления новых результатов.
Powered by POEM™ Engine Copyright © 2002-2005