stream_socket_recvfrom

(PHP 5, PHP 7)

stream_socket_recvfromПолучает данные из сокета, подключённого или нет

Описание

string stream_socket_recvfrom ( resource $socket , int $length [, int $flags = 0 [, string &$address ]] )

stream_socket_recvfrom() принимает данные из удалённого сокета размером до length байт.

Список параметров

socket

Удалённый сокет.

length

Количество байт для получения из параметра socket.

flags

Значение параметра flags может быть любой комбинацией из следующего:

Возможные значения для параметра flags
STREAM_OOB Обрабатывать данные OOB (out-of-band).
STREAM_PEEK Получать данные из сокета, но не расходовать буфер. Последующие вызовы функций fread() или stream_socket_recvfrom() получат те же самые данные.

address

Если указан параметр address, он будет заполнен адресом удалённого сокета.

Возвращаемые значения

Возвращает прочитанные данные в виде строки

Примеры

Пример #1 Пример использования функции stream_socket_recvfrom()

<?php
/* Открывает серверный сокет на 1234-м порту на localhost */
$server stream_socket_server('tcp://127.0.0.1:1234');

/* Принимает соединение */
$socket stream_socket_accept($server);

/* Получает пакет (обычный размер MTU 1500) OOB-данных */
echo "Получены данные OOB (Out-Of-Band): '" stream_socket_recvfrom($socket1500STREAM_OOB) . "'\n";

/* Получить обычные данные, но не расходовать их. */
echo "Данные: '" stream_socket_recvfrom($socket1500STREAM_PEEK) . "'\n";

/* Получить тот же самый пакет снова, но в этот раз удалить его из буфера данных. */
echo "Данные: '" stream_socket_recvfrom($socket1500) . "'\n";

/* Закрыть сокет */
fclose($socket);
fclose($server);
?>

Примечания

Замечание:

Если получено сообщение длиной больше, чем параметр length, лишние байты могут быть пропущены в зависимости от типа сокета, из которого получено сообщение (такого, как UDP).

Замечание:

Вызовы функции stream_socket_recvfrom() на потоках, основанных на сокетах, после вызовов потоковых функций, основанных на буферах (таких как fread() или stream_get_line()) читают данные непосредственно из сокета и пропускают потоковый буфер.

Смотрите также

  • stream_socket_sendto() - Отправляет сообщение в сокет, независимо от того, подсоединён он или нет
  • stream_socket_client() - Открыть соединение с интернет-сокетом или с доменным сокетом Unix
  • stream_socket_server() - Создаёт интернет-сокет или доменный сокет Unix
add a note add a note

User Contributed Notes 3 notes

up
8
cweiske at php dot net
7 years ago
Note that stream_socket_recvfrom() bypasses stream wrappers including TLS/SSL. While reading from an encrypted stream with fread() will return decrypted data, using stream_socket_recvfrom() will give you the original encrypted bytes.
up
1
raat1979 at gmail dot com
2 years ago
Basically there is currently no real way to determine what the position of the Out of band data is in the tcp/ip stream.

However, it seems that In my current environment (winsock: Windows / PHP 5.3.0) you do not peek beyond the OOB byte unless the buffer is empty
reads do read beyond the OOB data. (I'll check my linux box later)

You should be able to figure out the position of the OOB data by peeking and reading from the regular stream
although it would not be 100% reliable as we do read beyond the OOB data when nothing is in front of it.
depending on the high level protocol it might be possible
to handle the specific "no data in front of out-of-band data" case

<?php
echo "<pre>";
$sockets = stream_socket_pair(STREAM_PF_INET, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
$reader=$sockets[0];
$writer=$sockets[1];

stream_socket_sendto($writer,"abc");
stream_socket_sendto($writer,"xyZ",STREAM_OOB); // ONLY THE LAST BYTE IS MARKED AS OOB DATA
stream_socket_sendto($writer,"def");

echo
"\r\n";
echo
"Test 1, Peeking beyond oob when the read buffer becomes empty\r\n";
echo
"The data order is 'abcxyZdef'\r\n";
stream_select($r=array($reader), $w=array(), $x=array($reader),5);
echo
"has regular:";var_dump(count($r)!==0);
echo
"has oobData:";var_dump(count($x)!==0);
echo
"<span style='color:blue' >Peek (9) regular:".stream_socket_recvfrom($reader,9,STREAM_PEEK)."</span>\r\n";
echo
"<span style='color:green'>Peek (1) OobData:".stream_socket_recvfrom($reader,9,STREAM_OOB|STREAM_PEEK)."</span>\r\n";
echo
"<span style='color:black'>READ (4) regular:".stream_socket_recvfrom($reader,4)."</span>\r\n";
echo
"<span style='color:blue' >Peek (9) regular:".stream_socket_recvfrom($reader,9,STREAM_PEEK)."</span>\r\n";
echo
"<span style='color:black'>READ (1) regular:".stream_socket_recvfrom($reader,1)."</span>\r\n";
echo
"<span style='color:blue' >Peek (9) regular:".stream_socket_recvfrom($reader,9,STREAM_PEEK)."</span>\r\n";
// read the OOB data
echo "<span style='color:red'  >READ (9) OobData:".stream_socket_recvfrom($reader,9,STREAM_OOB)."</span>\r\n";

echo
"<span style='color:blue' >Peek (9) regular:".stream_socket_recvfrom($reader,9,STREAM_PEEK)."</span>\r\n";

fclose($sockets[0]);
fclose($sockets[1]);
echo
"</pre>";
?>
outputs:
Test 1, Peeking beyond oob when the read buffer becomes empty
The data order is 'abcxyZdef'
has regular:bool(true)
has oobData:bool(true)
Peek (9) regular:abcxy
Peek (1) OobData:Z
READ (4) regular:abcx
Peek (9) regular:y
READ (1) regular:y
Peek (9) regular:def
READ (9) OobData:Z
Peek (9) regular:def

<?php
echo "<pre>";
$sockets = stream_socket_pair(STREAM_PF_INET, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
$reader=$sockets[0];
$writer=$sockets[1];

stream_socket_sendto($writer,"Z",STREAM_OOB); // ONLY THE LAST BYTE IS MARKED AS OOB DATA
stream_socket_sendto($writer,"abcxydef");

echo
"<hr/>";
echo
"\r\n";
echo
"Test 2, peek if there is nothing in front of the OOB data\r\n";
echo
"The data order is 'Zabcxydef'\r\n";
stream_select($r=array($reader), $w=array(), $x=array($reader),5);
echo
"has regular:";var_dump(count($r)!==0);
echo
"has oobData:";var_dump(count($x)!==0);
echo
"<span style='color:blue'>peek (9) regular:".stream_socket_recvfrom($reader,9,STREAM_PEEK)."</span>\r\n";
echo
"<span style='color:red' >Peek (9) OobData:".stream_socket_recvfrom($reader,9,STREAM_OOB)."</span>\r\n";
echo
"<span style='color:blue'>peek (9) regular:".stream_socket_recvfrom($reader,9,STREAM_PEEK)."</span>\r\n";
echo
"</pre>";
?>
Outputs:
Test 2, peek if there is nothing in front of the OOB data
The data order is 'Zabcxydef'
has regular:bool(true)
has oobData:bool(true)
peek (9) regular:abcxydef
Peek (9) OobData:Z
peek (9) regular:abcxydef
up
1
MagicalTux at php dot net
6 years ago
This method may return a peer address not compatible with stream_socket_sendto() if in ipv6.

The ip returned by recvfrom is not within brackets ([]), and has the port appended, which makes it look like ::1:1234. To cut it properly, use strrpos()
To Top