socket_select立即返回false buth没有错误代码

问题描述:

我与socket_select玩,但有一个主机,这个功能确实奇怪的事情:立即socket_select立即返回false buth没有错误代码

  • 的回报,而不是等待5秒
  • 返回false,表示一些错误
  • socket_last_error()返回0(成功)。

此服务器的phpinfo()http://jsfiddle.net/Lmrfe/embedded/result/

$server = socket_create(AF_UNIX, SOCK_STREAM, 0); 
$r = socket_bind($server, '/some/file/somewhere'); 
$r = socket_listen($server); 
// none of the above socket_* returns false 

$t = microtime(true); 
socket_clear_error(); 

$read = array($server); $write = null; $except = null; 
$read = array($server); $write = array(); $except = array(); 
$read = array(); $write = array(); $except = array(); 
$read = null; $write = null; $except = null; 

$changed = socket_select($read, $write, $except, 5,0); 
$changed = socket_select($read, $write, $except, null); 
$changed = socket_select($read, $write, $except, 5000000); 
$changed = socket_select($read, $write, $except, 5000000, 0); 
$changed = socket_select($read, $write, $except, 5000000, 5000000); 

/* Results: 

    microtime(true) - $t == almost zero 

    $changed === false 

    socket_last_error() === 0 
    socket_strerror(socket_last_error()) === Success 

    $read === array(1) { 
    [0]=> 
    resource(2) of type (Socket) 
    } 
    $write === NULL 
    $except === NULL 
*/ 

$s = socket_read($server, 1024, PHP_BINARY_READ); 
// $s === false 

发生了什么事吗?

更新测试脚本:仍然运行在瞬间:

header('Content-Type: text/plain; charset=utf-8'); 
error_reporting(-1); 

for($i = 0; $i < 4; $i++){ 
for($j = 0; $j < 5; $j++){ 
    echo "\n\n\n\n\n[i,j]=[{$i},{$j}]\n"; 

    $socket = socket_create(AF_UNIX, SOCK_STREAM, 0); 
    var_dump('socket_create', $socket); echo "\n"; if($socket === false) continue; 

    $socket_file = dirname(__FILE__)."/test_socket_i{$i}_j{$j}"; 
    if(file_exists($socket_file)) unlink($socket_file); 

    $r = socket_bind($socket, $socket_file); 
    var_dump('socket_bind', $r); echo "\n"; if($r === false) continue; 

    $r = socket_listen($socket); 
    var_dump('socket_listen', $r); echo "\n"; if($r === false) continue; 

    $t = microtime(true); 
    socket_clear_error(); 

    if($i==0){ $read = null;    $write = null; $except = null; } 
    if($i==1){ $read = array();   $write = array(); $except = array(); } 
    if($i==2){ $read = array($socket); $write = null; $except = null; } 
    if($i==3){ $read = array($socket); $write = array(); $except = array(); } 

    if($j==0){ $changed = socket_select($read, $write, $except, 5,0); } // 5 seconds 
    if($j==1){ $changed = socket_select($read, $write, $except, null); } // forever 
    if($j==2){ $changed = socket_select($read, $write, $except, 5000000); } 
    if($j==3){ $changed = socket_select($read, $write, $except, 5000000, 0); } 
    if($j==4){ $changed = socket_select($read, $write, $except, 5000000, 5000000); } 

    var_dump('•socket_select returned:', $changed);echo "\n"; 
    var_dump('•$read/$write/$except:',$read,$write,$except);echo "\n"; 
    var_dump('•error:', socket_last_error(), socket_strerror(socket_last_error()));echo "\n"; 
    var_dump('time: ', microtime(true) - $t);echo "\n";    // almost zero 
}} 

如果你遇到了这个错误,你可以使用类似的东西围绕工作吧:

$socket_select_timeout_seconds = 5; 

while(true){ 
    $time_start = microtime(true); 
    $c = socket_select($r,$w,$e, $socket_select_timeout_seconds); 

    if(/* something happened */){ 
    // handle socket events 
    }else if(microtime(true) - $time_start < 0.01){ 
    // nothing happened, but buggy socket_select didn't wait 
    // wait manually 
    usleep($socket_select_timeout_seconds * 1000000); 
    } 

} 

你可能想使用的,而不是插座stream_ *功能。

流功能更通用,是PHP核心的一部分,而Socket支持需要安装。流功能给你基本上更多的控制权。

http://www.php.net/manual/en/intro.stream.php

检查此 http://php.net/manual/en/function.socket-select.php

由于在当前Zend引擎的限制,不可能通过一恒定改性剂像NULL直接作为参数传递给一个函数,它预计此参数来通过参考传递。而是使用一个临时变量或表达式最左边的部件是一个临时变量:

所以问题是,你是初始化$write = null

+0

您好,我究竟做如下的引用部分做例子:'$ E = NULL; socket_select($ r,$ w,$ e,0);'这是“禁止”语法我认为:'socket_select($ r,null,null,0);' – biziclop 2013-02-14 11:07:05

+0

虽然没有任何答案对此有解释错误,我因为你的声望最低而给你赏金。把它作为一个受欢迎的礼物:) – biziclop 2013-02-18 14:55:56

由于@Amez指出你不应该传递null值来选择。相反,对于未使用的socket_select()参数创建一个空数组:

$read = array($server); 
$write = array(); 
$except = array(); 
$changed = socket_select($read, $write, $except, 5,0); 

我刚刚在Python中同样的问题绊倒了(我不知道为什么PHP/Python将不会简单地替换空值作为内部机智空数组对于选择这当然似乎是预期的行为)。

+0

谢谢你的回答,我用更广泛的测试更新了我的问题,它仍然没有任何等待地运行。某种程度上,服务器可能配置错误。在我的实际代码中,我已经创建了一个简单的自适应等待解决方案来防止100%CPU使用率那么,没有什么是完美的(尤其是PHP)。 – biziclop 2013-02-17 10:41:38