stream_socket_recvfrom

(PHP 5, PHP 7, PHP 8)

stream_socket_recvfrom从连接或未连接的套接字接收数据

描述

stream_socket_recvfrom(
    资源 $socket,
    整数 $length,
    整数 $flags = 0,
    ?字符串 &$address = null
): 字符串|false

stream_socket_recvfrom() 从远程套接字接受数据,最多 length 字节。

参数

socket

远程套接字。

length

要从 socket 接收的字节数。

flags

flags 的值可以是以下任何组合

flags 的可能值
STREAM_OOB 处理 OOB (out-of-band) 数据。
STREAM_PEEK 从套接字检索数据,但不消耗缓冲区。后续对 fread()stream_socket_recvfrom() 的调用将看到相同的数据。

address

如果提供了 address,它将被填充为远程套接字的地址。

返回值

返回读取的数据,以字符串形式,或在失败时返回 false

示例

示例 #1 stream_socket_recvfrom() 示例

<?php
/* 在本地主机上打开一个到端口 1234 的服务器套接字 */
$server = stream_socket_server('tcp://127.0.0.1:1234');

/* 接受连接 */
$socket = stream_socket_accept($server);

/* 获取一个 OOB 数据包(1500 是一个典型的 MTU 大小) */
echo "接收到的带外数据: '" . stream_socket_recvfrom($socket, 1500, STREAM_OOB) . "'\n";

/* 窥视正常的带内数据,但不要消耗它。 */
echo "数据: '" . stream_socket_recvfrom($socket, 1500, STREAM_PEEK) . "'\n";

/* 再次获取完全相同的数据包,但这次将其从缓冲区中删除。 */
echo "数据: '" . stream_socket_recvfrom($socket, 1500) . "'\n";

/* 关闭它 */
fclose($socket);
fclose($server);
?>

注释

注意:

如果接收到的消息长度超过 length 参数,则可能会丢弃多余的字节,具体取决于接收消息的套接字类型(例如 UDP)。

注意:

在基于套接字的流上调用 stream_socket_recvfrom() 时,在调用基于缓冲区的流函数(如 fread()stream_get_line())之后,会直接从套接字读取数据,绕过流缓冲区。

另请参阅

添加注释

用户贡献的注释 3 个注释

cweiske at php dot net
14 年前
请注意,stream_socket_recvfrom() 会绕过流包装器,包括 TLS/SSL。虽然从加密流使用 fread() 读取将返回解密数据,但使用 stream_socket_recvfrom() 会得到原始加密字节。
MagicalTux at php dot net
13 年前
如果在 ipv6 中,此方法可能会返回与 stream_socket_sendto() 不兼容的对等地址。

recvfrom 返回的 ip 没有在括号 ([]) 内,并且附加了端口,这使得它看起来像 ::1:1234。要正确地截断它,请使用 strrpos()
raat1979 at gmail dot com
9 年前
基本上,目前还没有真正的方法来确定带外数据的在 tcp/ip 流中的位置。

但是,在我的当前环境(winsock: Windows / PHP 5.3.0)中,似乎除非缓冲区为空,否则您不会窥视带外字节。
读取确实会读取带外数据之外的数据。(我稍后会检查我的 Linux 机器)

您可以通过窥视和从常规流读取来确定带外数据的的位置。
虽然它不会 100% 可靠,因为当带外数据前面没有数据时,我们确实会读取带外数据之外的数据。
根据高级协议,它可能是可能的。
处理特定的“带外数据前面没有数据”情况

<?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
To Top