2011-03-22 73 views
4

我有一點的代碼,簡化的,看起來像:如何檢測stream_copy_to_stream錯誤?

 
$fout = fsockopen($host, 80); 
stream_set_timeout($fout, 10*3600); // 10 hours 
$fin = fopen($file, 'rb'); // not really a file stream, but good enough proxy here 
$readbytes = stream_copy_to_stream($fin, $fout); 
if(!$readbytes) die('copy failed'); 

不過,我有時會收到以下類型的錯誤:

 
Notice: stream_copy_to_stream(): send of 952 bytes failed with errno=104 Connection reset by peer in ... 
Notice: stream_copy_to_stream(): send of 952 bytes failed with errno=32 Broken pipe in ... 

而且在$檢查readbytes不會選擇錯誤。 我知道有可能使用複製的字節數來檢查文件的總長度,但只有在可以預先確定流的總長度的情況下才有效。由於這種情況是隨機發生的,我認爲連接只是因爲某種奇怪的原因而被放棄(但如果有人有任何建議來減少這種情況發生的可能性,那麼我都是耳朵)。但能夠知道轉讓是否完全成功,這將是一件好事。 反正有檢測問題,而無需:

  • 不必知道流的長度提前
  • 鉤到PHP錯誤處理程序拿起錯誤

...或也許使用緩衝fread/fwrite循環,檢查寫入的字節長度,這裏是最好的解決方案?

謝謝。

回答

3

好了,所以這是我流的複製功能,這試圖檢測錯誤,但它似乎失敗還是(和我想的fwrite是爲了返回正確的字節數)

function stream_copy($in, $out, $limit=null, $offset=null) { 
    $bufsize = 32*1024; 
    if(isset($offset)) fseek($in, $offset, SEEK_CUR); 
    while(!feof($in)) { 
     if(isset($limit)) { 
      if(!$limit) break; 
      $data = fread($in, min($limit,$bufsize)); 
     } else 
      $data = fread($in, $bufsize); 
     $datalen = strlen($data); 
     $written = fwrite($out, $data); 
     if($written != $datalen) { 
      return false; // write failed 
     } 
     if(isset($limit)) $limit -= $datalen; 
    } 
    return true; 
}

在上面的函數,即使在顯示錯誤時,我仍然會返回'true'。

所以我只是想嘗試掛鉤到PHP的錯誤處理程序。沒有測試以下,但我的猜測是,它應該工作

function stream_copy_to_stream_testerr($source, $dest) { 
    $args = func_get_args(); 

    global $__stream_copy_to_stream_fine; 
    $__stream_copy_to_stream_fine = true; 

    set_error_handler('__stream_copy_to_stream_testerr'); 
    call_user_func_array('stream_copy_to_stream', $args); 
    restore_error_handler(); 

    return $__stream_copy_to_stream_fine; 
} 
function __stream_copy_to_stream_testerr() { 
    $GLOBALS['__stream_copy_to_stream_fine'] = false; 
    return true; 
}

醜陋,但我可以看到的唯一解決方案。

+0

你有沒有遇到過這種情況?對於這部分:*(我認爲fwrite是爲了返回正確數量的字節)* - 我認爲這是網絡流的正確行爲,例如檢查'socket_write'文檔。好吧,這是一個不同的擴展,但我敢打賭真正的錢流擴展使用標準套接字函數在幕後,並因此顯示相同的行爲。 – Robin 2011-07-27 19:00:42