当服务器未指定文件末尾时,读到 XML 响应的末尾?



我正在编写一个通过XML与服务器通信的脚本。我可以说我要对服务器的API提出成功请求,因为我可以在接收到的服务器上的日志中看到,但是我很难收到响应(XML(。我不拥有服务器,不幸的是无法修改发送响应的任何程序。

我不认为服务器指定文件的末尾,因此执行while (!feof($fp)) { ... }挂起。不幸的是,我认为在阅读响应之前,我没有任何方法(据我所知(确定响应的大小。

我在做什么以及我尝试的事情:

function postXMLSocket ($server, $path, $port, $xmlDocument) {
  $contentLength = strlen($xmlDocument);
  $result = '';
  // Handling error case in else statement below
  if ($fp = @fsockopen($server, $port, $errno, $errstr, 30)) {
    $out =  "POST / HTTP/1.0rn";
    $out .= "Host: ".$server."rn";
    $out .= "Content-Type: text/xmlrn";
    $out .= "Content-Length: ".$contentLength."rn";
    $out .= "Connection: closern";
    $out .= "rn"; // all headers sent
    $out .= $xmlDocument;
    fwrite($fp, $out);
    // ATTEMPT 5: Read until we have a valid XML doc -- hangs
    // libxml_use_internal_errors(true);
    // do {
    //   $result .= fgets($fp, 128);
    //   $xmlTest = simplexml_load_string($result);
    // } while ($xmlTest === false);
    // ATTEMPT 4: Read X # of lines -- works but I can't know how many lines response will be
    // for ($i = 0; $i < 10; $i++) {
    //   $result .= fgets($fp, 128);
    // }
    // ATTEMPT 3: Read until the lines being read are empty -- hangs
    // do {
    //   $lineRead = fgets($fp, 500);
    //   $result .= $lineRead;
    // } while (strlen($lineRead) > 0);
    // ATTEMPT 2: Read the whole file w/ fread -- only reads part of file
    // $result = fread($fp, 8192);
    // ATTEMPT 1: Read to the EOF -- hangs
    // while (!feof($fp)) {
    //   $result .= fgets($fp, 128);
    // }
    fclose($fp);
  }
  else {
    // Could not connect to socket
    return false;
  }
  return $result;
}

尝试描述:

1(首先,我只是尝试阅读行,直到到达文件的末尾。这一直在悬挂并导致时间耗尽,我认为这是因为服务器没有标记其响应的XML文件的末尾,因此它被捕获在无限的循环中。

2(第二我试图将响应读为一个整个文件。这奏效了,我得到了一些东西,但这是不完整的(似乎响应很大(。虽然这起作用,但我没有任何方法可以在阅读响应之前有多大,所以我认为这是一种选择。

3(接下来我尝试阅读,直到fgets返回一个空字符串。我做出了一个假设,如果它通过文件末尾读取行,它将这样做,但这也悬挂。

4(对于此尝试读它。

5(这是我以为我变得聪明的地方。我知道响应将是XML,并且将包含在<Response>节点中。因此,我以为我可以逃脱阅读,直到$result变量包含有效的XML字符串,但这似乎也挂起。

使用较高级别的方法http请求可能会为您提供帮助。尝试以下操作:

$stringWithSomeXml = "your payload xml here";
postXml("www.google.com", "/path/on/server", 80, $stringWithSomeXml);
function postXml($server, $path, $port, $xmlPayload)
{
    $ch = curl_init();
    $path = ltrim($path, "/");
    if ($port == 80) {
        $url = "https://{$server}/{$path}";
    } else {
        $url = "https://{$server}:{$port}/{$path}";
    }
    echo "n$urln";
    curl_setopt(
        $ch,
        CURLOPT_URL,
        $url
    );
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt(
        $ch,
        CURLOPT_HTTPHEADER,
        [
            "Content-type: application/xml",
            "Content-Length: ".strlen($xmlPayload)
        ]
    );
    curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlPayload);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    $result = curl_exec($ch);
    echo "length: " . strlen($result) . "n";
    echo "content: " . $result . "n";
    curl_close($ch);
}

最新更新