【问题标题】:What is blocking fsockopen?什么是阻止 fsockopen?
【发布时间】:2012-05-15 08:41:52
【问题描述】:

苦苦挣扎了半天,终于通过转换这个函数让reCAPTCHA工作了:

function _recaptcha_http_post($host, $path, $data, $port = 80) {

 $req = _recaptcha_qsencode ($data);

 $http_request  = "POST $path HTTP/1.0\r\n";
 $http_request .= "Host: $host\r\n";
 $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
 $http_request .= "Content-Length: " . strlen($req) . "\r\n";
 $http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
 $http_request .= "\r\n";
 $http_request .= $req;

 $response = "";
 if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
  die ("Could not open socket");
 }

 fwrite($fs, $http_request);

 while ( !feof($fs) )
  $response .= fgets($fs, 1160); // One TCP-IP packet
 fclose($fs);
 $response = explode("\r\n\r\n", $response, 2);
 return $response;
}

到:

function _recaptcha_http_post($host, $path, $data, $port = 80) {
 $req = _recaptcha_qsencode ($data);
 $request = curl_init("http://".$host.$path);

 curl_setopt($request, CURLOPT_USERAGENT, "reCAPTCHA/PHP");
 curl_setopt($request, CURLOPT_POST, true);
 curl_setopt($request, CURLOPT_POSTFIELDS, $req);
 curl_setopt($request, CURLOPT_RETURNTRANSFER, true);

 $response = curl_exec($request);
 return $response;
}

基本上,我很想知道为什么curl 有效,而fsockopen 因“无法打开套接字”而失败。谢谢。

另外:已启用套接字支持。

【问题讨论】:

  • stfu 运算符 (@) 可消除错误。这使得找出问题所在非常困难。
  • @chris,错误是“php_network_getaddresses: getaddrinfo failed: Name or service not known”。有什么帮助吗?
  • 我猜你的 $host 值不正确。请参阅 fsockopen() 的文档
  • @chris,我也这么认为。但是$host 只是“www.google.com”。
  • +1 让我的 recaptcha 使用 curl 代码。您能否判断您是否也在 recaptcha_check_answer 函数中进行了任何特定于 curl 的更改

标签: php curl fsockopen


【解决方案1】:

我可能是错的,但是你在fsockopen() 中使用$port = 80 而在 cURL 的情况下根本没有使用这个变量。尝试通过 port 80 而不是端口 443 连接到 SSL 时,我遇到了同样的问题;据我所知,cURL 默认检查 SSL 并进行相应的连接。

另外,尝试使用 CURLOPT_VERBOSE 运行 cURL 以查看它的作用。

【讨论】:

  • 感谢您迟到的答案,但我尝试在旧代码上使用端口 443。它也不起作用。
【解决方案2】:

if(false === ...) 里面的 $errno 和 $errstr 是什么?那么,如果你改成

会输出什么
 if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
  die ("Could not open socket, error: " . $errstr);
 }

【讨论】:

  • 它说“php_network_getaddresses: getaddrinfo failed: Name or service not known”
  • 什么是 说?
  • 在调用 fsockopen 之前转储它时,$host 中有什么?如果你用它的IP替换它怎么办?如果您尝试在您正在测试此代码的服务器上解析此主机名,它会这样做吗?如果您有访问权限,请尝试从那里的 shell ping $host。
  • $hostfsockopen 调用之前转储时为“www.google.com”。如果我将其替换为 ip 地址“74.125.235.52”,错误就会消失,但我从fgets($fs, 1160) 得到的响应是 bool(false)。
  • 如果您从该服务器外壳执行“ping google.com”(您可以访问它吗?),它是否解析为 IP?
【解决方案3】:

Googling 你的错误导致怀疑你的 /etc/resolv.conf 是否可以被 PHP 读取。在 bash 中执行 ls -lah /etc/resolv.conf 以查看它是否可读。你会得到类似的东西:

myserver:~ myname$ ls -lah /ets/resolv.conf
lrwxr-xr-x  1 root  wheel    20B 16 mrt  2011 /etc/resolv.conf
       ^ if there is an 'r' here it is readable. if you have '-' here, it is not.

如果它不可读,请尝试在 bash 中执行:chmod 644 /etc/resolv.conf 以使其可读。

【讨论】:

    【解决方案4】:

    哇,

      if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
      die ("Could not open socket");
     }
    

    这当然没有任何意义。试试:

        $fs = fsockopen($host, $port, $errno, $errstr, 10); // @ ignores errors
     if(!$fs) die ("Could not open Socket");
    

    此外,Skype 有时也会阻塞端口 80。

    【讨论】:

    • 确实有道理。在 PHP 中,赋值的结果是被赋值的值。所以 $fs 得到 fsockopen 的返回值,然后该值也被测试是否为 false。这就是$x = $y = $z = 42; 一次将 42 分配给所有三个变量的方式。
    • omg,现在我也回答了这个问题,但在意识到你提出了这个 16 个月大的问题之前:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多