gpt4 book ai didi

php - fsockopen 连接在超时之前不会关闭

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:45:43 24 4
gpt4 key购买 nike

背景:我必须创建一个普通站点,它接受传入的已发布 XML 并通过套接字连接将 XML 发送到服务器,然后显示从服务器发回的 XML。简单易行。

问题:我在使用 fsockopen() 连接到服务器并发送 XML 时没有遇到任何问题。从服务器读取 XML 是一个全新的问题。正常的

while (!feof($fp)) {    
echo fgets($fp);
}

没有成功,因为服务器返回一个 XML 字符串,并且只返回一个 XML 字符串(没有长度信息、eof、eol 等)。因此它将等到超时,显示接收到的 XML 和超时错误。我的问题类似于这个 dinosaur

简而言之,我想在套接字上读取 XML 并在没有更多数据发送时立即关闭它(不是等待超时)。将超时设置为较低的值也不可行,因为服务器响应可能在 2--30 秒之间变化。

解决方案:折腾了一个下午,我决定把这个问题的解决方案分享如下(大家批评指正)。

$fp = fsockopen("123.456.789.1", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)";
} else {
$wait = true;
$out = '<samplexml><item>something</item></samplexml>';

// [1] disable blocking
stream_set_blocking($fp, 0);
fwrite($fp, $out);

while (!feof($fp)) {
$r = fgets($fp);
echo $r;
if (!strcmp($r, "")){
if (!$wait) {
// [2] has recieved data on this socket before
break;
}
} else {
$wait = false;
}
}
fclose($fp);
}

事实证明,我的主要问题是阻塞。所以首先,[1] 我必须禁用 stream_set_blocking 以便 fgets() 可以持续检查新数据是否可用。如果未禁用,fgets() 将从服务器获取 XML,然后循环将在第二次尝试时卡住,因为它将等待更多数据可用(永远不会)。

我知道一旦我们读取了一些数据,如果返回任何空的 fgets() 就可以立即关闭连接(因此我们仍然可以设置 fgets 的第二个参数() 如果有必要的话)。

使用这个网站几个月后,我终于在 stackoverflow 上发布了一些东西。

最佳答案

这段代码有几个问题:

  • 首先,比较 strcmp($r, "") 实际上没有意义。它有效,但没有意义。我不认为fgets永远返回一个空字符串。如果没有更多可用数据,则返回 FALSE。您的比较有效的原因是 FALSE 被转换为空字符串。但这会使您的代码不清晰。
  • 其次,由于流处于非阻塞模式,因此数据可能只是暂时不可用。通过在 fgets 返回 false 时立即中断循环,您可能只读取操作系统缓存的第一批数据。您尝试通过强制等待尚未收到任何数据来解决此问题,但这是一个脆弱的解决方案。
  • 最后,你忙着循环等待数据。这是非常耗费资源的。

最后两点可以用stream_select解决。 .通过这种方式,您可以在收到第一个数据包之前强制执行较大的超时,然后使用较小的超时。

关于php - fsockopen 连接在超时之前不会关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6573738/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com