背景:我必须创建一个普通站点,该站点接受传入的已发布 XML,并通过套接字连接将 XML 发送到服务器,然后显示从服务器发回的 XML。十分简单。
问题:我使用fsockopen()连接到服务器并发送 XML没有问题。从服务器读取 XML 是一个全新的问题。正常的
while (!feof($fp)) {
echo fgets($fp);
}
没有成功,因为服务器返回一个 XML 字符串,并且只返回一个 XML 字符串(没有长度信息、eof、eol 等)。因此它会等到超时,显示接收到的 XML 和超时错误。我的问题与这只恐龙相似。
简而言之,我想在套接字上读取 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 上发布了一些东西。