One Method to Bypass The Bug #11058 of PHP
最近接触PHP很多,由于PHP也就接触了才一年,因此遇到了不少问题,其中当时让我比较头疼是一个因为PHP自身的Bug而引起的麻烦。
开始我是想抓取一个页面的源代码:
<?php $content = file_get_contents("http://www.iron-feet.cn/"); echo $content; ?>
很简单的代码,当时觉得肯定不会有问题的,但是在我的本机上(环境是IAMP)一运行,报错:
php_network_getaddresses: getaddrinfo failed
当时极其的纳闷,两行代码怎么看都没有错误。于是乎,我将文件上传到我的虚拟主机(环境是LAMP)上,一运行,结果一样让我失望,报相同的错误。
查看了N久,未果。在我百般无奈之下,寻找PHP官网,最后发现这个错误是由于PHP的一个Bug所引起的。
该Bug主要的原因是PHP在某些情况下,无法正确访问DNS。而且这个“某些情况下”目前还不得而知,有些情况下这个Bug就不作祟,有些情况下就开始发作了。这个Bug不但导致了file_get_contents函数的不能正常工作,别的只要需要通过访问DNS实现的函数都会出现这个Bug。
经过多方测试和查看,发现唯一能解决这个错误的方法就是修改hosts,让PHP不需要访问DNS直接通过hosts实现域名解析。
但是这个显然是个治标不治本的方法,因为很多虚拟主机是不会允许用户随意修改hosts,我所使用的这个虚拟主机就是这样的。
我当时就想,我的虚拟主机也有这个Bug,但是我主机里面的Wordpress却很正常的运作着,肯定有别的什么解决的方法。
经过对Wordpress文件的分析,才发现其实解决的方法很容易。当网上那些提问的人都在考虑和寻求如何解决这个Bug的时候,却没有人想过怎么去避开这个Bug。
Wordpress访问网络是通过两套方案的,一套就是上述所说的利用PHP原生的函数;一套就是通过调用curl来实现。
PHP可以通过LibCurl来实现网络的访问和操作,而且比原生的要强很多。
<?php $ch = curl_init(); $timeout = 5; curl_setopt($ch, CURLOPT_URL, "http://www.iron-feet.cn"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); $contents = curl_exec($ch); echo $contents; curl_close($ch); ?>
利用Libcurl几行代码就可以避免PHP的这个原生Bug。也不需要修改hosts了。但是需要肯定的是:您的虚拟主机必须支持Libcurl。
只要通过
<?php phpinfo(); ?>
就可以查看您的主机是否支持Libcurl了
再次可以肯定的是:目前主流的虚拟主机,Libcurl是基本都会支持的,但是hosts是不可能允许你修改的。还是尽量使用Libcurl吧,即使你现在没有遇到这个Bug,也不能保证万一哪天你要把你文件移到别的主机运行不会遇到这个Bug。
同时衷心希望PHP官方能快点Fix掉这个Bug
Push







对于非追求 DIY 的用户,直接 require 一个 Snoopy PHP 库可能更适合哦。
Snoopy的确是个非常好用的库。
当时看Wordpress文件的时候,他们的两套方案也是用的snoopy库