PHP异步GET请求在一台服务器上工作,但不工作;另一方面


PHP Async GET request works on one server, but doesn't on the other

请查看底部的编辑以获取更多信息

我有两台服务器。两者都应该能够通过GET请求相互调用。为了发出请求(实际上,触发事件比发出请求更重要),我使用了以下代码:

function URLCallAsync($url, $params, $type='POST')
{
      foreach ($params as $key => &$val) {
        if (is_array($val)) $val = implode(',', $val);
        $post_params[] = $key.'='.urlencode($val);
      }
  $post_string = implode('&', $post_params);
  $parts=parse_url($url);
  $fp = fsockopen($parts['host'],
      isset($parts['port'])?$parts['port']:80,
      $errno, $errstr, 30);
  // Data goes in the path for a GET request
  if('GET' == $type) $parts['path'] .= '?'.$post_string;
  $out = "$type ".$parts['path']." HTTP/1.1'r'n";
  $out.= "Host: ".$parts['host']."'r'n";
  $out.= "Content-Type: application/x-www-form-urlencoded'r'n";
  $out.= "Content-Length: ".strlen($post_string)."'r'n";
  $out.= "Connection: Close'r'n'r'n";
  // Data goes in the request body for a POST request
  if ('POST' == $type && isset($post_string)) $out.= $post_string;
  fwrite($fp, $out);
  fclose($fp);
}

我在两台服务器上为函数提供了完全相同的数据(但url)(我复制了调用文件来测试它!!),但它只在一个方向上工作!

我把对该函数的调用写在日志文件中,这样我就可以调查是否出了问题。

服务器A->服务器B,工作正常,服务器A的日志文件包含正确的url

服务器B->服务器A,只在服务器B的日志文件中打印正确的信息,但服务器A从未收到请求。

发生这种事的原因是什么?

编辑:可能是不同种类的服务器吗?服务器A是nginx,服务器B是apache。服务器A的url中也有一个"~"符号,也许这就是问题所在?get请求的参数是用php的"urlencode"编码的,这可能会产生问题?

我试了一下,但问题仍然是请求没有通过服务器a。但从浏览器来看,它以某种方式运行得很好(假设我输入了带参数的正确URL)。

第2版:如果我用"file_get_contents"交换"URLCallAsync",它的工作原理应该是这样的。但问题是file_get_contents正在阻塞!所以它只能是函数本身。但奇怪的是,它的工作方向相反:(

第3版:函数"URLCallAsync"运行顺利,没有任何错误、通知或其他任何事情。只是其他服务器没有接收到它。file_get_contents到底有什么不同???

我让它工作起来了。

经过大量的wireshark操作,我发现file_get_contents甚至比我的异步函数更简单!

它只是完全省略了Content-Length字段!它只提供"GET…"answers"Host"。它也使用HTTP/1.0而不是1.1,但这并没有改变任何东西。

因此,解决方案是:同时发布Content-Length标头(由于我使用了GET,因此其值为0)将以某种方式使服务器拒绝请求。我不确定是服务器拒绝了请求,还是其他什么,比如防火墙可能检测到了"格式错误"的请求,但至少问题得到了解决。

因此,下次发送请求时,如果不需要,请不要提供Content-Length标头:)