这里只有两点需要注意
- 在 UNIX 上,如果设置了 SO_DEBUG,php 程序需要一个有效的用户 ID 为 0。
- 在套接字上激活 SO_OOBINLINE 等同于将 MSG_OOB 标志传递给与该套接字一起使用的每个接收函数(例如:socket_recv、socket_recvfrom)。
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
socket_get_option — 获取套接字的套接字选项
socket_get_option() 函数检索指定 socket
的 option
参数指定的选项的值。
socket
使用 socket_create() 或 socket_accept() 创建的 Socket 实例。
level
level
参数指定选项所在的协议级别。例如,要检索套接字级别的选项,将使用 SOL_SOCKET
的 level
参数。其他级别,例如 TCP
,可以通过指定该级别的协议号来使用。协议号可以通过使用 getprotobyname() 函数找到。
option
选项 | 描述 | 类型 |
---|---|---|
SO_DEBUG |
报告是否正在记录调试信息。 | int |
SO_BROADCAST |
报告是否支持广播消息的传输。 | int |
SO_REUSEADDR |
报告是否可以重用本地地址。 | int |
SO_REUSEPORT |
报告是否可以重用本地端口。 | int |
SO_KEEPALIVE |
报告连接是否通过定期传输消息保持活动状态。如果连接的套接字未能响应这些消息,则连接将断开,并且写入该套接字的进程将收到 SIGPIPE 信号。 | int |
SO_LINGER |
报告如果存在数据, 如果 l_onoff 非零且 l_linger 为零,则所有未发送的数据将被丢弃,并且在面向连接的套接字的情况下,将向对等方发送 RST(重置)。 另一方面,如果 l_onoff 非零且 l_linger 非零,则 socket_close() 将阻塞,直到所有数据发送完毕或 l_linger 中指定的时间过去。如果套接字是非阻塞的,则 socket_close() 将失败并返回错误。 |
array。该数组将包含两个键:l_onoff 和 l_linger。 |
SO_OOBINLINE |
报告 socket 是否将带外数据留在线内。 |
int |
SO_SNDBUF |
报告发送缓冲区的大小。 | int |
SO_RCVBUF |
报告接收缓冲区的大小。 | int |
SO_ERROR |
报告有关错误状态的信息并将其清除。 | int(无法通过 socket_set_option() 设置) |
SO_TYPE |
报告 socket 类型(例如 SOCK_STREAM )。 |
int(无法通过 socket_set_option() 设置) |
SO_DONTROUTE |
报告传出消息是否绕过标准路由设施。 | int |
SO_RCVLOWAT |
报告 socket 输入操作要处理的最小字节数。 |
int |
SO_RCVTIMEO |
报告输入操作的超时值。 | array。该数组将包含两个键:sec 是超时值的秒部分,usec 是超时值的微秒部分。 |
SO_SNDTIMEO |
报告超时值,指定输出函数由于流量控制阻止数据发送而阻塞的时间量。 | array。该数组将包含两个键:sec 是超时值的秒部分,usec 是超时值的微秒部分。 |
SO_SNDLOWAT |
报告 socket 输出操作要处理的最小字节数。 |
int |
TCP_NODELAY |
报告是否禁用了 Nagle TCP 算法。 | int |
MCAST_JOIN_GROUP |
加入多播组。 |
array,包含键 "group" ,指定一个 string,其中包含 IPv4 或 IPv6 多播地址,以及 "interface" ,指定接口号(类型 int)或接口名称的 string ,例如 "eth0" 。可以指定 0 来指示应使用路由规则选择接口。(只能在 socket_set_option() 中使用) |
MCAST_LEAVE_GROUP |
离开多播组。 |
array。有关更多信息,请参见 MCAST_JOIN_GROUP 。(只能在 socket_set_option() 中使用) |
MCAST_BLOCK_SOURCE |
阻止从特定源到特定多播组(必须已加入)的传入数据包。 |
array,与 MCAST_JOIN_GROUP 具有相同的键,另外还有一个额外的键 source ,它映射到一个 string,指定要阻止的源的 IPv4 或 IPv6 地址。(只能在 socket_set_option() 中使用) |
MCAST_UNBLOCK_SOURCE |
解除阻止(重新开始接收)来自特定源地址到特定多播组(必须已加入)的传入数据包。 |
array,格式与 MCAST_BLOCK_SOURCE 相同。(只能在 socket_set_option() 中使用) |
MCAST_JOIN_SOURCE_GROUP |
接收目的地址为特定多播组且源地址与特定值匹配的数据包。 |
array,格式与 MCAST_BLOCK_SOURCE 相同。(只能在 socket_set_option() 中使用) |
MCAST_LEAVE_SOURCE_GROUP |
停止接收目的地址为特定多播组且源地址与特定值匹配的数据包。 |
array,格式与 MCAST_BLOCK_SOURCE 相同。(只能在 socket_set_option() 中使用) |
IP_MULTICAST_IF |
IPv4 多播数据包的传出接口。 | 可以是指定接口号的 int,也可以是包含接口名称(例如 eth0 )的 string。值 0 可以用于指示要使用路由表来选择接口。函数 socket_get_option() 返回接口索引。请注意,与 C API 不同,此选项不采用 IP 地址。这消除了 IP_MULTICAST_IF 和 IPV6_MULTICAST_IF 之间的接口差异。 |
IPV6_MULTICAST_IF |
IPv6 多播数据包的传出接口。 | 与 IP_MULTICAST_IF 相同。 |
IP_MULTICAST_LOOP |
IPv4 数据包的多播环回策略启用或禁用传出多播的环回,这些多播必须已加入。但是,其效果在类 Unix 系统和 Windows 上不同,前者在接收路径上,而后者在发送路径上。 |
int(0 或 1 )。对于 socket_set_option(),任何值都将被接受,并将根据通常的 PHP 规则转换为布尔值。 |
IPV6_MULTICAST_LOOP |
类似于 IP_MULTICAST_LOOP ,但针对 IPv6。 |
int。参见 IP_MULTICAST_LOOP 。 |
IP_MULTICAST_TTL |
传出 IPv4 多播数据包的生存时间。这应该是一个介于 0(不离开接口)和 255 之间的数字。默认值为 1(仅到达本地网络)。 | int,介于 0 和 255 之间。 |
IPV6_MULTICAST_HOPS |
类似于 IP_MULTICAST_TTL ,但针对 IPv6 数据包。还接受 -1 值,表示应使用默认路由。 |
int 在 -1 到 255 之间。 |
SO_MARK |
在 Linux 上为套接字设置一个标识符,用于数据包过滤。 | int |
SO_ACCEPTFILTER |
在监听套接字上添加一个接受过滤器(FreeBSD/NetBSD)。在 FreeBSD 上需要预先加载一个接受过滤器内核模块(例如 accf_http)。 | string 过滤器的名称(最大长度 15 个字符)。 |
SO_USER_COOKIE |
在 FreeBSD 上为套接字设置一个标识符,用于数据包过滤。 | int |
SO_RTABLE |
在 OpenBSD 上为套接字设置一个标识符,用于数据包过滤。 | int |
SO_DONTTRUNC |
保留未读数据。 | int |
SO_WANTMORE |
当更多数据准备好时给出提示。 | int |
TCP_DEFER_ACCEPT |
在数据准备好之前不要通知监听套接字。 | int |
SO_INCOMING_CPU |
获取/设置套接字的 CPU 亲缘性。 | int |
SO_MEMINFO |
获取套接字的所有内存信息。 | int |
SO_BPF_EXTENSIONS |
获取内核支持的 BPF 扩展,用于附加到套接字。 | int |
SO_SETFIB |
设置套接字的路由表(FIB)。(仅限 FreeBSD) | int |
SOL_FILTER |
分配给套接字的过滤器。(仅限 Solaris/Illumos) | int |
TCP_KEEPCNT |
设置 TCP 在丢弃连接之前应发送的保持活动探测的最大数量。 | int |
TCP_KEEPIDLE |
设置连接需要保持空闲的时间。 | int |
TCP_KEEPINTVL |
设置单个保持活动探测之间的时间间隔。 | int |
TCP_KEEPALIVE |
设置连接需要保持空闲的时间。(仅限 macOS) | int |
TCP_NOTSENT_LOWAT |
设置套接字流的写队列中未发送数据的限制数量。(仅限 Linux) | int |
返回给定选项的值,或者在失败时返回 false
。
示例 #1 socket_get_option() 示例
<?php
$socket = socket_create_listen(1223);
$linger = array('l_linger' => 1, 'l_onoff' => 1);
socket_set_option($socket, SOL_SOCKET, SO_LINGER, $linger);
var_dump(socket_get_option($socket, SOL_SOCKET, SO_REUSEADDR));
?>
这里只有两点需要注意
- 在 UNIX 上,如果设置了 SO_DEBUG,php 程序需要一个有效的用户 ID 为 0。
- 在套接字上激活 SO_OOBINLINE 等同于将 MSG_OOB 标志传递给与该套接字一起使用的每个接收函数(例如:socket_recv、socket_recvfrom)。
如果使用 Unix 套接字,并且想要使用 SO_PEERCRED,可以使用数字 17 作为 optname(并将 SOL_SOCKET 作为级别)。连接进程的 PID 将被返回。
我一直在尝试使用这个选项来使用具有相同主机名和相同端口的多个套接字连接(IRC)。但是,为此需要的套接字函数是 SO_REUSEPORT。
虽然大多数 Linux 发行版尚未在其发行版中正式实现该功能。
但是,对于 Debian,有一个可以安装的补丁来使其工作
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c617f398edd4db2b8567a28e899a88f8f574798d
它有一些工作要做,但我在一段时间后成功了(Debian 新手),也许其他一些人遇到了和我一样的問題。
要接收专用接口上的 UDP DHCP 数据包,必须使用未记录的选项 SO_BINDTODEVICE
<?php
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_set_option($socket, SOL_SOCKET, SO_BINDTODEVICE, 'eth1');
socket_set_option($socket, SOL_SOCKET, SO_BROADCAST, 1);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_set_option($socket, SOL_SOCKET, SO_REUSEPORT, 1);
socket_bind($socket, '255.255.255.255', 67);
while (1) {
if ($src = @socket_recv($socket, $data, 9999, 0)) {
echo $data . PHP_EOL;
}
}
?>