如何检测stream_copy_to_stream错误?

时间:2011-03-22 01:28:11

标签: php

我有一些代码,简化,看起来像:

$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循环,检查写入的字节长度,这里是最好的解决方案吗?

感谢。

1 个答案:

答案 0 :(得分: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;
}

丑陋,但我能看到的唯一解决方案。