Работа с сокетами, как быть с тайм-аутом?

jeka!

Просто Member
Работа с сокетами, как быть с тайм-аутом?

В обшем умучился с этими сокетами в ПХП!
Сначала юзал fsockopen(), в результате заметил что
если удалённый сервер не отвечает, то сокет ожидает
ответ в любом случае, и этот процесс может длиться
офигенно долгое время, у меня 4 часа висел...
Далее полазил тут по топикам, нашел несколько тем
по этому поводу, пишут используй socket_set_timeout();
И тут хренушки!
Это баг очевидный, таймауты не устанавливаются, пробовал на 3
операционках. Под индой один раз заметил, что таймаут поставился,
но всего 1 раз :(
Далее начал юзать такой вариант:
PHP:
$port = getservbyname('www','tcp');
$sk = socket_create(AF_INET, SOCK_STREAM, getprotobyname("TCP"));
if ($sk < 0) echo socket_strerror($sk);
$result = socket_connect($sk, gethostbyname($host), $port);
if ($result < 0) echo socket_strerror($sk);
		$put  = "HEAD ".$path." HTTP/1.0\r\n";
		$put .= "Host: ".$host."\r\n\r\n";
$head = '';
socket_write($sk, $put, strlen($put));
while ($out = socket_read($sk, 1024)) $head .= $out;
if (!preg_match("!HTTP/(\d{1}\.\d{1})\s+(\d{3})\s+!s", $head, $get))
echo "hren, a ne connect!";
socket_close($sk);
Тут тоже самое, механизм походу один, и глючный.
Тут же вобще нет возможности установить тайм аут.
По крайней мере в мане я этого не нашел.
Какие могут быть выходы?
Сейчас начал переписывать всё на перл, там похожий
механизм, думаю что возможно результат будет тот же.\
На край можно ещё на С попробывать...
В общем кто сталкивался с этим и как решил проблему, напишите...
 

tony2001

TeaM PHPClub
[m]fsockopen[/m]
[m]stream_set_blocking[/m]
в обеих функциях указать таймаут (в первом случае - на коннект, во втором - на чтение данных).
и все.
 

jeka!

Просто Member
Ну и что мне это даст? пробовал, stream_set_blocking может снять только блокировку, при этом программа завершается, и не получает данные.
Эту методу можно применить только на отправку данных, а после установки stream_set_blocking(FP, FALSE), чтение не происходит, уже пробовал.
PHP:
$fp = fsockopen("localhost", 80, &$errno, &$errstr, 30);
if(!$fp) {
    echo "Unable to open - $errno : $errstr\n";
} else {
	var_dump(socket_get_status($fp));
    fputs($fp, "GET /index.html HTTP/1.0\n\n");
    $start = time();
	socket_set_blocking($fp, false);
    socket_set_timeout($fp, 15);
    $res = fread($fp, 2000);
    var_dump(socket_get_status($fp));
    fclose($fp);
    print $res;
}
Результат:

array(5) {
["stream_type"]=>
string(6) "socket"
["unread_bytes"]=>
int(0)
["timed_out"]=>
bool(false)
["blocked"]=>
bool(true)
["eof"]=>
bool(false)
}
array(5) {
["stream_type"]=>
string(6) "socket"
["unread_bytes"]=>
int(0)
["timed_out"]=>
bool(false)
["blocked"]=>
bool(false)
["eof"]=>
bool(false)
}

А вот это не появляетя :
HTTP/1.1 404 Not Found
Date: Wed, 08 Jan 2003 11:59:16 GMT
Server: Apache/1.3.27 (Win32) PHP/4.3.0
Connection: close
Content-Type: text/html; charset=iso-8859-1

Так что это не походит...
 

jeka!

Просто Member
Сходи по ссылке, специально пример выложил, всё настраивается:

http://phpscript.ru/example/socket.php

Я почитал что изменилось в новой версии пхп, там пишут про сокеты что только добавлены некоторые функции и о поддержки stream_set_timeout в окнах, но ничего они не сделали с этим делом, может им отписать, что мол у вас баг там?
 

tony2001

TeaM PHPClub
jeka:
ты юзаешь socket_*, a это экспериментальный экстеншен.
тот рецепт, который я дал, работает с fsockopen - проверено.
причем, работает с не самыми новыми версиями РНР.
 

jeka!

Просто Member
Как это? вот то что я юзаю, хотя по разному пробовал всё равно не ставится!
PHP:
$fp = fsockopen("localhost", 80, &$errno, &$errstr, 3);
if (!$fp) {
    echo "Unable to open - $errno : $errstr\n";
} else {
    print_r(stream_get_meta_data($fp));
    fputs($fp, "HEAD /index.html HTTP/1.0\nHost: localhost\n\n");
    stream_set_blocking($fp, false);
    stream_set_timeout($fp, 15);
    $res = fread($fp, 2000);
    print_r(stream_get_meta_data($fp));
    fclose($fp);
    echo $res;
}
Приведи тогда пример, какая схема работает....
 

tony2001

TeaM PHPClub
>stream_set_blocking($fp, false);
можно убрать.

>Приведи тогда пример, какая схема работает....
твоя, без set_blocking
 

jeka!

Просто Member
tony2001 >>
ЕКЛМН! Специально для тебя сделал!
http://phpscript.ru/example/socket.php
Там отключается то то то это, посмотри не пашет!
Там просто стоит:
PHP:
if ($_POST['blocking'] == 2) stream_set_blocking($fp, false);
По этому это то отключается, то ставится.
 

tony2001

TeaM PHPClub
укажи хост: phpclub.net
путь: /
timeout = true
blocking = false

объясни мне что это должно означать для тебя ?
 

jeka!

Просто Member
Array
(
[stream_type] => socket
[unread_bytes] => 0
[timed_out] =>
[blocked] => 1
[eof] => 1
)

Ну и чего? timed_out = пусто, значет не установился...
 

tony2001

TeaM PHPClub
>Ну и чего? timed_out = пусто, значет не установился...
это значит "запрос не отвалился по таймауту".

timed_out (bool) - TRUE if the stream timed out while waiting for data on the last call to fread() or fgets().
 

jeka!

Просто Member
Ну хорошо, допустим так всё и должно работать, скажи мне тогда, почему когда я запускаю по крону свой валюедатор ссылок, он у меня виснет по 5 часов на ссылке которая не отвечает???
Это тайм аут её так выключает да?
 
Сверху