我试图以非阻塞的方式向流中写入大量数据(~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()
不是一种选择。
答案 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状态,否则您将最终阻止自己。