socket_write с неблокирующими сокетами

sitecreator

Новичок
socket_write с неблокирующими сокетами

PHP:
$s1 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$s2 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

socket_set_nonblock($s1);
socket_set_nonblock($s2);

@socket_connect($s1, "localhost", 80);
@socket_connect($s2, "localhost", 80);


$w = array($s1,$s2);

$n = socket_select($r=NULL, &$w, $f=NULL, 2);

if ($n !=0)	// если есть готовые для записи сокеты
{
	foreach ($w as $key => $s)
	{
		$wr = socket_write($s, "GET /test.php HTTP/1.0\n\n");
	}
}
Не совсем пойму как работает socket_write с неблокирующими сокетами.
По идее этот оператор передает управление следующему оператору сразу же, не дожидаясь окончания операции записи в сокет.
Тогда, что в таком случае содержит переменная $wr (количество записанных байт)? За какой период записанных?

Правильно ли я понимаю, что далее стоит использовать фунцию socket_select для определения сокетов, готовых для чтения? Т. е. если сокет готов для чтения, то можно считать, что socket_write выполнилась успешно, конечно, если сокет не перечислен в массиве ошибок ($except)?
 

ONK

Пассивист PHPСluba
sitecreator, при записи в неблокирующий сокет, в него запишется столько "сколько сможет записаться", пределить записалось ли всё призвано какраз возвращаемое этой функцией значение.
Далее, если записалось не всё, то с помощью socket_select ожидаем готовности сокета к записи следующего пакета.
С чтением всё тоже самое.
 

sitecreator

Новичок
ONK, при чтении из неблокирующего сокета socket_read получает данные из буфера, где УЖЕ находятся поступившие данные, готовые для чтения, так ведь?

А как обстоит дело с записью? socket_write принимает данные для отправки в некий буфер сколько может (и возвращает это количество) и потом их отправляет? Или socket_write передает данные сразу же во внешний мир сколько успеет за время выполнения текущего оператора?
 

ONK

Пассивист PHPСluba
sitecreator, с записью всё точно также как с чтением, данные поступаю в I/O буфер выделенный для этого сокета ОС, далее за доставку данных по назначению отвечает ОС, а конкретно драйвер выбранного протокола.
 

sitecreator

Новичок
ONK, а если драйвер выбранного протокола не доставит полностью данные? Как я об этом узнаю? Будет сгенерирована ошибка для сокета?
 

voodoo

Новичок
можно получить
а) готовый к чтению сокет в select, и при чтении -1 (если сокет был закрыт той стороной)
б) -1 при попытке записи
в) SigPIPE (если кабель порвался и прошло пару часов без активности)

по моему так(с)
 

sitecreator

Новичок
voodoo, "при чтении -1" - что имеется ввиду? Какая функция возвращает "-1"? socket_last_error?

в) SigPIPE - это константа? Возвращается функцией socket_last_error?
 

voodoo

Новичок
в варианте а) -1 возвращает socket_read (т.к. читать нечего, сокет закрыт).

SigPIPE -- это сигнал, ловится через php.net/pcntl_signal
 

ONK

Пассивист PHPСluba
voodoo, в ПХП socket_read, в описанном случае, вместо -1 возвращает пустую строку.

sitecreator, при следующем вызове socket_select проверит готов ли сокет на запись/чтение следующего пакета данных и не произошло ли в нёи исключений (не разорвано ли соединение). В случае готовности к записи/чтения, сокет будет в соответствующем массиве. В случае исключения будет тоже самое, но при попытке записи в него запишется 0 байт, а в случае чтения считается пустая строка.
 

voodoo

Новичок
о... -1 это да...
хотя в доках написано вернут FALSE (оба, и запись и чтение), наверное лучше === делать.
 

ONK

Пассивист PHPСluba
voodoo, там же в комментарях к документации сказано, что при двоичном считывании, при обрыве соединения socket_read возвращает пустую строку, следовательно лучше обработать за раз оба исключения чем проверять их по одному.
My tests (on PHP 5.1.4) show that when you socket_read() on a shutdown-socket, it returns FALSE when using PHP_NORMAL_READ, but returns "" when reading in PHP_BINARY_READ.
Тоже самое с записью, если сокет готов к записи, и при этом в него не удалось ничего записать, значит он не в порядке. Хотя такое предположение делать не корректно, т.к. в документации ничего об этом не сказано (я пока ни с какими граблями от такого подхода не встречался).
 
Сверху