неблокирующий fsockopen?

  • Автор темы Автор темы gray07
  • Дата начала Дата начала

gray07

Новичок
неблокирующий fsockopen?

С помощью функции stream_set_blocking можно задать неблокирующий режим для соккетов, и fread будет возвращать результат сразу. А как можно сделать, чтобы fsockopen тоже работала в неблокирующем режиме, тоесть чтобы выполнение скрипта не останавливалось на время, пока установится tcp/ip соединение? Я так подозреваю может помочь модуль Sockets...
 
>Я так подозреваю может помочь модуль Sockets...
да.
socket_select(), socket_connect().
 
думаю вашу проблема состоит из 2-х.
1-я в fsockopen вы конектитесь не к IP а к хосту, тогда php запускает сначала функцию gethostbyname() прежде чем перейдет к непосредсвенному коннекту.
2-я проблема при конекте через IP лучьше использовать функции $s = socket_create();
а потом
socket_set_nonblock($s);
а уж затем socket_connect($ip, $port)
и дальше уже ловити сокет в массиве от socket_select()
 
Столкнулся с проблемой определения, закрыто уже соединение, или нет. Функция feof() ругается, что ресурс не есть stream
 
gray07

Вполне логично, что сокет не есть дескриптор открытого файла.
 
но в таком случае невозможно определить, закрыто соединение, или нет socket_read
возвращает "" и в случае, когда данные не пришли (в случае неблокирующего соккета), и когда соединение закрыто.
 
ну вот например мануал говорит, про socket_read
socket_read() returns the data as a string on success, or FALSE on error (including if the remote host has closed the connection).
но для неблокирующего соккета это не так, он возвращает пустую строку, если соединение закрыто.
это баг?

-~{}~ 20.10.08 14:57:

linux, PHP 5.2.4-2ubuntu5.3 with Suhosin-Patch 0.9.6.2
 
gray07
Принципиально не читаем про socket_select() ?
 
ладно, приведу код (я вообще-то пишу irc бота, отправка http запросов это просто для теста)

PHP:
<?php

$host = 'www.google.com'; 
$ip = gethostbyname($host);

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$res = socket_connect($socket, $ip, 80);
if(!$res) die("socket_connect error");
socket_set_nonblock($socket);

$query = "GET / HTTP/1.0\r\nHost: $host\r\n\r\n";
socket_write($socket, $query) or die("socket_write error");

$finished = false;
do {
	do {
		usleep(100000);
		$changed = socket_select($r=array($socket), $w=array($socket), $null, 0);
	} while (!$changed);

	do {
		$data = socket_read($socket, 1024);
		var_dump($data);
		if($data === false) $finished = true;
	} while($data);
} while(!$finished)

?>

выдает

string(587) "HTTP/1.0 302 Found
Location: http://www.google.com.ua/
....
</BODY></HTML>
"
string(0) ""
string(0) ""

и дальше бесконечный цикл

я что-то делаю не так?
 
gray07

Хотите честно?
Код для нелокирующихся сокетов - полное дерьмо.

>я что-то делаю не так?

Не читаете то, что вам предлогают почитать (уже раза три).
 
Автор оригинала: ys
gray07

Хотите честно?
Код для нелокирующихся сокетов - полное дерьмо.

>я что-то делаю не так?

Не читаете то, что вам предлогают почитать (уже раза три).
Я читал мануал. Укажите хоть одну ошибку.
 
для начала сделай http client который параллельно обрабатывает 5 запросов - вот и поймешь ;)
 
ты намекаешь, что в коде, который я привел, файл качается в один поток?

я столкнулся с проблемой, что не могу определить, было закрыто соединение, или нет. чтобы не приводить весь код своего irc бота, я написал короткий пример с загрузкой одного файла по http.

возможно мне намекали, что нужно проверять, что возвращается в первом параметре socket_select? так вот, если исправить код так
PHP:
	do {
		usleep(100000);
		$changed = socket_select($r=array($socket), $w=array($socket), $e=array($socket), 0);
	} while (count($r)==0);
это ничего не меняет

теперь собственно что я хочу спросить. то, что socket_read при закрытии соединения не возвращает false, как описано в мануале - это баг? и каким образом можно определить, закрылось соединение, или нет
 
Eсли на одном из сокетов произошло что-либо, то
Код:
$do = true;
while ($do == true) {
            $str = socket_read($socket, 1024);
	if ($str == "") {
		$do = false;
                        ...
            }
}
 
Feofan

Да канэшна, socket_last_error() используют только последние лохи..
 
ys, а что socket_last_error() в случае закрытия соединения выдает правильную ошибку? у меня он выдает только Resource temporarily unavailable и в случае закрытия соединения, и когда пока нету данных, чтобы читать

-~{}~ 22.10.08 15:34:

гм, "Resource temporarily unavailable" она возвращает только при первом вызове, потом "Success", даже когда соединение закрыто

-~{}~ 22.10.08 15:46:

наконец то я разобрался, когда нету данных, чтобы читать, fread возвращает false, а socket_last_error() возвращает ошибку "Resource temporarily unavailable", когда же соединение закрыто, fread возвращает "", а socket_last_error() 0, тобишь "Success"

-~{}~ 22.10.08 15:47:

Но все равно, хоть убейте меня, в мануале это не описано полностью
 
Я не поленился еще раз пройти документацию.
Хотя мне это нафиг не нужно, но за10 минут у меня получился рабочий вариант:

PHP:
$host = 'www.google.com';
$ip = gethostbyname($host);
$reads = array();

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$res = socket_connect($socket, $ip, 80);
if(!$res) die("socket_connect error");
socket_set_nonblock($socket);

$query = "GET / HTTP/1.0\r\nHost: $host\r\n\r\n";
socket_write($socket, $query) or die("socket_write error");

$all_ok = true;
$reads[] =$socket;
do {
                $reads=array($socket);
               $s = socket_select($reads, $writes = NULL, $excepts = NULL, 0);
                if ($s) {
                        foreach($reads as $r) {
                                $res = socket_recv($r, $data, 1024, 0);
                                if ($res === FALSE ) {
                                        continue;
                                } else if ($res < 0) {
                                        echo "some shit happened\n";
                                        $all_ok = false;
                                } else if ($res === 0) {
                                        echo "remote side  is closed connection\n";
                                        $all_ok = false;
                                } else {
                                        echo $data;
                                }
                        }
                }
} while ($all_ok);
 
ys
Очень интересно, почему же ты его не использовал??
Вывод: ....
 
Feofan

Ответ, как про неуловимого Джо - оно мне нафиг не нужно.
Достаточно?
 
Сверху