2013-02-08 39 views
3

我與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 
}} 

回答

1

如果你遇到了這個錯誤,你可以使用類似的東西圍繞工作吧:

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

} 
3

檢查此 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

2

由於@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

相關問題