我目前正在使用以下方法对 resource
进行哈希处理以进行查找:
$foo = socket_create(...);
$bar = socket_create(...);
$map[(int)$foo] = 'foo';
$map[(int)$bar] = 'bar';
echo $map[(int)$foo]; // "foo"
integer
是否是最好的选择?如果不是,还有什么其他哈希方法会更好或更有效?这些查找将在一个紧密循环(套接字轮询)中每秒数百次的集合中执行,因此我已经排除了基于迭代的解决方案。
编辑:
为了更好地解释我的情况,socket_select()
函数通过引用获取套接字资源数组并修改它们,以便在函数调用之后,它们将仅包含已更改的资源(例如,准备好被阅读)。我使用 Socket
类作为套接字资源的包装器,以使我的代码更加抽象和可测试:
$socketObject = new Socket($socketResource);
我的另一个类保留了每次我们调用 socket_select()
时需要轮询的所有套接字资源的列表:
$reads = [$socketResource1, $socketResource2, ...];
socket_select($reads, null, null, 0);
调用 socket_select()
后,我知道哪个套接字资源发生了变化,但是要在我的代码中做任何有意义的事情,我需要知道哪个套接字objects 这些资源对应。因此,我需要一些方法将套接字资源映射到它们的对象:
foreach ($reads as $socketResource) {
// Which socket object does $socketResource correspond to here?
// Currently, I use a solution like this:
$socketObject = $this->map[(int)$socketResource];
// Unfortunately, this behavior isn't guaranteed, so it isn't reliable...
}
最佳答案
casting resources to integer 时观察到的行为未定义(请参阅页面底部的注意事项)。所以即使这个works now and reliably did for a long time ,您必须意识到,没有通知就可以不更改。
澄清后编辑:
不要将资源作为键,而是使用两个数组。一种是将 Socket 对象的哈希值映射到实际对象。另一个将相同的哈希值映射到资源。然后将后一个数组传递给 socket_select
。在函数不会改变数组key的前提下,可以再遍历数组,使用key查找Socket,时间复杂度O(1):
$r1 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$r2 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$s1 = new Socket($foo);
$s2 = new Socket($bar);
$socketMap = array(
spl_object_hash($s1) => $s1,
spl_object_hash($s2) => $s2
);
$reads = array(
spl_object_hash($s1) => $r1,
spl_object_hash($s2) => $r2
);
socket_select($reads, null, null, 0);
foreach (array_keys($reads) as $hash) {
$socketObject = $socketMap[$hash];
}
更新:将资源转换为整数不再是未定义的,如链接手册页中所示。如果将资源转换为整数,则结果将是 PHP 在运行时分配给该资源的唯一资源编号。
关于php - 在 PHP 中使用资源作为数组索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17776219/