PHP流写缓冲区

时间:2012-11-15 02:31:31

标签: php sockets php-socket

我试图以非阻塞的方式向流中写入大量数据(~250K)。

抽象出复杂性和对象结构,这就是我正在运行的东西:

$fp = fsockopen('host', 80);
socket_set_blocking( $fp, false );
fwrite( $fp, $string, $length ); // Where $string is a 250K string

然而,数据并非全部都被写入。假设这是PHP的写缓冲区,我设置了stream_set_write_buffer( $fp, 0 ),但这也没有解决问题。

我把我的fwrite打成了4096B的块 - 看起来客户端发送了3个完整的批次(4096字节)和第四批的~1500B。对fwrite的任何和所有连续调用都会返回0字节。

有没有人知道如何将这些数据排队以非阻塞的方式发送出去?如果我删除socket_set_blocking( $fp, false ); - 一切正常。很明显,这是异步运行它的问题。

你有什么想法?套接字扩展是否会对此有所帮助?它以不同的方式处理缓冲区吗?

注意:我故意编写此套接字传输层以避免因各种原因使用curl。使用curl_multi()不是一种选择。

2 个答案:

答案 0 :(得分:5)

您的问题几乎可以肯定是因为非阻塞套接字流上的fwrite操作可能会因新数据包的到达而中断。因此,您不能指望fwrite是原子的。在这种情况下,必须依赖于fwrite调用的返回值,以确切地告诉您在该传递中写入流的字节数,并继续写入,直到发送完所有数据。

例如......

$dataToWrite = 'my data';
$bytesToWrite = strlen($dataToWrite);
$totalBytesWritten = 0;

while ($totalBytesWritten < $bytesToWrite) {
    $bytes = fwrite($mySock, substr($dataToWrite, $totalBytesWritten));
    $totalBytesWritten += $bytes;
}

显然,对此问题的有效处理还必须考虑到套接字连接消失等情况。

答案 1 :(得分:0)

您是否在考虑阻止和重试?我假设您需要考虑EAGAIN / EWOULDBLOCK / EINTR状态,否则您将最终阻止自己。