【问题标题】:How to detect stream_copy_to_stream errors?如何检测 stream_copy_to_stream 错误?
【发布时间】:2011-03-22 01:28:11
【问题描述】:

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

$fout = fsockopen($host, 80); stream_set_timeout($fout, 10*3600); // 10个小时 $fin = fopen($file, 'rb'); // 不是真正的文件流,但这里的代理足够好 $readbytes = stream_copy_to_stream($fin, $fout); if(!$readbytes) die('复制失败');

但是,我有时会收到以下类型的错误:

注意:stream_copy_to_stream():发送 952 字节失败,errno=104 Connection reset by peer in ... 注意:stream_copy_to_stream(): 发送 952 字节失败,errno=32 Broken pipe in ...

并且在那里检查 $readbytes 不会发现错误。 我知道可以通过复制的字节数检查文件的总长度,但这只有在可以提前确定流的总长度时才有效。

由于这种情况是随机发生的,我认为连接只是由于某种奇怪的原因而被断开(但如果有人有任何建议来减少这种情况发生的可能性,我会全力以赴)。但是很高兴能够知道转移是否完全成功。 无论如何都可以在没有以下情况下检测问题:

  • 必须提前知道流的长度
  • 挂钩到 PHP 错误处理程序以获取错误

...或者也许使用缓冲的 fread/fwrite 循环,检查写入的字节长度,这是最好的解决方案?

谢谢。

【问题讨论】:

    标签: php


    【解决方案1】:

    好的,这是我的流复制功能,尝试检测错误,但它似乎仍然失败(我认为 fwrite 是为了返回正确的字节数)

    函数 stream_copy($in, $out, $limit=null, $offset=null) {
        $bufsize = 32*1024;
        if(isset($offset)) fseek($in, $offset, SEEK_CUR);
        而(!feof($in)){
            如果(isset($limit)){
                if(!$limit) 中断;
                $data = fread($in, min($limit,$bufsize));
            } 别的
                $data = fread($in, $bufsize);
            $datalen = strlen($data);
            $written = fwrite($out, $data);
            如果($写入!= $datalen){
                返回假; // 写入失败
            }
            if(isset($limit)) $limit -= $datalen;
        }
        返回真;
    }

    在上述函数中,即使显示错误,我仍然会返回“true”。

    所以我将尝试挂钩到 PHP 的错误处理程序。尚未测试以下内容,但我的猜测是它应该工作

    函数 stream_copy_to_stream_testerr($source, $dest) {
        $args = func_get_args();
    
        全局 $__stream_copy_to_stream_fine;
        $__stream_copy_to_stream_fine = 真;
    
        set_error_handler('__stream_copy_to_stream_testerr');
        call_user_func_array('stream_copy_to_stream', $args);
        restore_error_handler();
    
        返回 $__stream_copy_to_stream_fine;
    }
    函数 __stream_copy_to_stream_testerr() {
        $GLOBALS['__stream_copy_to_stream_fine'] = false;
        返回真;
    }

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

    【讨论】:

    • 你在这方面有什么收获吗?对于这部分:(我认为 fwrite 是为了返回正确的字节数) - 我认为这是网络流的正确行为,例如查看 socket_write 文档。好的,这是一个不同的扩展,但我敢打赌,流扩展在幕后使用标准套接字函数,因此显示相同的行为。
    猜你喜欢
    • 2013-10-17
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-02
    • 2021-09-22
    • 2011-06-10
    相关资源
    最近更新 更多