2

我正在尝试以非阻塞方式将大量数据(~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()不是一种选择。

4

2 回答 2

5

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

例如 ...

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

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

显然,对这个问题的稳健处理还必须考虑到套接字连接消失等情况。

于 2012-11-15T03:12:50.053 回答
0

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

于 2012-11-15T03:12:41.777 回答