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

gray07

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

С помощью функции stream_set_blocking можно задать неблокирующий режим для соккетов, и fread будет возвращать результат сразу. А как можно сделать, чтобы fsockopen тоже работала в неблокирующем режиме, тоесть чтобы выполнение скрипта не останавливалось на время, пока установится tcp/ip соединение? Я так подозреваю может помочь модуль Sockets...
 

tony2001

TeaM PHPClub
>Я так подозреваю может помочь модуль Sockets...
да.
socket_select(), socket_connect().
 

DolgoV

Новичок
думаю вашу проблема состоит из 2-х.
1-я в fsockopen вы конектитесь не к IP а к хосту, тогда php запускает сначала функцию gethostbyname() прежде чем перейдет к непосредсвенному коннекту.
2-я проблема при конекте через IP лучьше использовать функции $s = socket_create();
а потом
socket_set_nonblock($s);
а уж затем socket_connect($ip, $port)
и дальше уже ловити сокет в массиве от socket_select()
 

gray07

Новичок
Столкнулся с проблемой определения, закрыто уже соединение, или нет. Функция feof() ругается, что ресурс не есть stream
 

ys

отодвинутый новичок
gray07

Вполне логично, что сокет не есть дескриптор открытого файла.
 

gray07

Новичок
но в таком случае невозможно определить, закрыто соединение, или нет socket_read
возвращает "" и в случае, когда данные не пришли (в случае неблокирующего соккета), и когда соединение закрыто.
 

gray07

Новичок
ну вот например мануал говорит, про 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
 

ys

отодвинутый новичок
gray07
Принципиально не читаем про socket_select() ?
 

gray07

Новичок
ладно, приведу код (я вообще-то пишу 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) ""

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

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

ys

отодвинутый новичок
gray07

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

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

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

gray07

Новичок
Автор оригинала: ys
gray07

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

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

Не читаете то, что вам предлогают почитать (уже раза три).
Я читал мануал. Укажите хоть одну ошибку.
 

fixxxer

К.О.
Партнер клуба
для начала сделай http client который параллельно обрабатывает 5 запросов - вот и поймешь ;)
 

gray07

Новичок
ты намекаешь, что в коде, который я привел, файл качается в один поток?

я столкнулся с проблемой, что не могу определить, было закрыто соединение, или нет. чтобы не приводить весь код своего 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, как описано в мануале - это баг? и каким образом можно определить, закрылось соединение, или нет
 

Feofan

Новичок
Eсли на одном из сокетов произошло что-либо, то
Код:
$do = true;
while ($do == true) {
            $str = socket_read($socket, 1024);
	if ($str == "") {
		$do = false;
                        ...
            }
}
 

ys

отодвинутый новичок
Feofan

Да канэшна, socket_last_error() используют только последние лохи..
 

gray07

Новичок
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:

Но все равно, хоть убейте меня, в мануале это не описано полностью
 

ys

отодвинутый новичок
Я не поленился еще раз пройти документацию.
Хотя мне это нафиг не нужно, но за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);
 

Feofan

Новичок
ys
Очень интересно, почему же ты его не использовал??
Вывод: ....
 

ys

отодвинутый новичок
Feofan

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