Php socket\u select立即返回false,但没有错误代码

Php socket\u select立即返回false,但没有错误代码,php,unix-socket,Php,Unix Socket,我正在玩socket\u select,但是在一个主机上,这个函数会做一些奇怪的事情: 立即返回,而不是等待5秒 返回false,表示存在错误 但是socket\u last\u error()返回0(成功) 此服务器的phpinfo(): 这里发生了什么 更新的测试脚本:仍在瞬间运行: header('Content-Type: text/plain; charset=utf-8'); error_reporting(-1); for( $i = 0; $i < 4; $i++ )

我正在玩
socket\u select
,但是在一个主机上,这个函数会做一些奇怪的事情:

  • 立即返回,而不是等待5秒
  • 返回false,表示存在错误
  • 但是
    socket\u last\u error()
    返回0(成功)
此服务器的
phpinfo()

这里发生了什么

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

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
}}
标题('Content-Type:text/plain;charset=utf-8');
错误报告(-1);
对于($i=0;$i<4;$i++){
对于($j=0;$j<5;$j++){
echo“\n\n\n\n[i,j]=[{$i},{$j}]\n”;
$socket=socket\u create(AF\u UNIX,SOCK\u流,0);
变量转储($socket\u create',$socket);如果($socket===false),则返回“\n”;继续;
$socket\u file=dirname(\u\u file)。\“/test\u socket\u i{$i}\u j{$j}”;
如果(文件_存在($socket_文件))取消链接($socket_文件);
$r=socket\u绑定($socket,$socket\u文件);
var_dump('socket_bind',$r);如果($r===false),则返回“\n”;
$r=插座\u监听($socket);
var_dump('socket_listen',$r);如果($r===false)继续,则回显“\n”;
$t=微时间(真);
套接字清除错误();
如果($i==0){$read=null;$write=null;$except=null;}
如果($i==1){$read=array();$write=array();$except=array();}
如果($i==2){$read=array($socket);$write=null;$except=null;}
如果($i==3){$read=array($socket);$write=array();$except=array();}
如果($j==0){$changed=socket_选择($read,$write,$except,5,0);}//5秒
如果($j==1){$changed=socket_选择($read,$write,$except,null);}//
如果($j==2){$changed=socket_select($read,$write,$except,5000000);}
如果($j==3){$changed=socket_select($read,$write,$except,5000000,0);}
如果($j==4){$changed=socket_select($read,$write,$except,50000005000000);}
变量转储(“•套接字选择返回:”,$changed);回显“\n”;
变量转储(“•$read/$write/$except:”,$read,$write,$except);回显“\n”;
变量转储(“•错误:”,套接字最后一个错误(),套接字最后一个错误());回显“\n”;
var_dump('time:',microtime(true)-$t);echo“\n”//几乎为零
}}

您可能希望使用流函数而不是套接字

流函数更通用,是PHP核心的一部分,而需要安装套接字支持。流函数基本上为您提供了更多的控制

检查此项

由于当前Zend引擎中的限制,不可能将NULL等常量修饰符直接作为参数传递给期望通过引用传递此参数的函数。而是使用临时变量或最左侧成员为临时变量的表达式:


因此,问题是您正在初始化
$write=null

,正如@Amez指出的那样,您不应该将null值传递给select。相反,为未使用的
socket\u select()
参数创建一个空数组:

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

我最近在python中偶然发现了同样的问题(我不知道为什么PHP/python不会简单地在内部用空数组替换空值,因为select这显然是预期的行为)。

如果您遇到此错误,您可以使用类似的方法来解决:

$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 );
  }

}
$socket\u选择\u超时\u秒=5;
while(true){
$time\U start=微时间(真);
$c=套接字选择($r、$w、$e、$socket\u选择\u超时\u秒);
如果(/*发生了什么事*/){
//处理套接字事件
}else if(微时间(真)-$time\u start<0.01){
//什么也没发生,但buggy socket_select没有等
//手动等待
usleep($socket\u select\u timeout\u seconds*1000000);
}
}

Hi,我的操作与下面引用的部分完全相同:
$e=NULL;插座选择($r、$w、$e、0)socket\u select($r,null,null,0)虽然没有一个答案可以解释这个错误,但我为你颁发了奖金,因为你的声誉最低。把它当作欢迎的礼物:)谢谢你的回答,我用一个更广泛的测试更新了我的问题,这个测试仍然不用等待。服务器可能以某种方式配置错误。在我的实际代码中,我已经创建了一个简单的自适应等待解决方案,以防止100%的CPU使用率。好吧,没有什么是完美的(尤其是php:)。
$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 );
  }

}