Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP流写入缓冲区_Php_Sockets_Php Socket - Fatal编程技术网

PHP流写入缓冲区

PHP流写入缓冲区,php,sockets,php-socket,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\u set\u write\u buffer($

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

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

$fp = fsockopen('host', 80);
socket_set_blocking( $fp, false );
fwrite( $fp, $string, $length ); // Where $string is a 250K string
然而,并不是所有的数据都被写入。假设这是PHP的写缓冲区发挥作用,我设置了
stream\u set\u write\u buffer($fp,0)
,但这也没有解决问题

我将我的fwrite分为4096B块,看起来客户端发送了3个完整的批(4096字节),第四批发送了1500B。对fwrite的任何和所有连续调用都返回写入的0字节

有人知道我如何将这些数据排队以非阻塞方式发送出去吗?如果我移除
socket\u set\u阻塞($fp,false)-一切正常。因此,显然异步运行它是一个问题

你的想法是什么?插座扩展在这里有帮助吗?它处理缓冲区的方式不同吗


注意:我有意编写这个套接字传输层,以避免出于各种原因使用curl。使用
curl\u multi()
不是一个选项。

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

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

例如

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

while ($totalBytesWritten < $bytesToWrite) {
    $bytes = fwrite($mySock, substr($dataToWrite, $totalBytesWritten));
    $totalBytesWritten += $bytes;
}
$dataToWrite='my data';
$bytesToWrite=strlen($dataToWrite);
$totalBytesWrited=0;
而($totalBytesWrite<$bytesToWrite){
$bytes=fwrite($mySock,substr($dataToWrite,$totalbytesswrite));
$totalBytesWrited+=$bytes;
}

显然,对该问题的有效处理还必须考虑套接字连接断开等情况。

您应该使用
socket\u select()
来确定套接字是否已准备好写入。由于文件限制问题,如果不重新编译PHP,则无法使用socket\u select。对此,select()系统调用相对较差。-这是我唯一的选择吗?你说的文件限制问题是什么意思?你有多少个套接字?这是在一个web服务器上运行的,该服务器能够为数百个网站和成吨的请求提供服务。尽管我只打开了一个套接字,但我们远远超出了1024个最大打开文件的默认限制。这是select()系统调用的一个限制。您有一个1/4兆字节的字符串吗?这样做可能会影响服务器的性能。是的,但在第一次写入返回部分写入后,对fwrite的所有后续调用似乎都返回0-尽管套接字报告它仍然处于打开状态。@colinmoreli那么您应该使用
stream\u select
,并且仅当它告诉您流可以接受写入操作而不阻塞时才进行写入。您可能还需要验证套接字是否仍处于活动状态。您可以使用
is\u资源($stream)&&来实现这一点!feof($stream)
请参见我刚才对自己答案的评论-很遗憾,stream_select在我们的环境中不起作用。此外,我确信插座连接可用<代码>是资源($stream)&!feof($stream)
返回true,只需使套接字同步,一切都会按预期工作。没有断开连接。我可能在第一次评论中撒了谎。我刚刚意识到我没有使用fwrite的返回值来减少$BytesWrite,我只是从我试图写入的字节总数中减去。我明天会做这些修改,然后回来发表评论。你在这方面是对的——这种方法确实有效。我们没有走这条路,但我还是接受了这个答案。