经过数小时尝试调试遇到 fopen() 问题的第三方应用程序后,我终于发现
php -r 'echo(file_get_contents("http://www.google.com/robots.txt"));'
失败,但是
php -r 'echo(file_get_contents("http://173.194.32.81/robots.txt"));'
成功。请注意,作为网络服务器用户,我可以 ping www.google.com 并且解决得很好。
我跟踪了 PHP 的两个执行,它们的分歧是这样的:
对于数字 v4 URL:
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("173.194
poll([{fd=3, events=POLLOUT}], 1, 0) = 0 (Timeout)
...[bunch of poll/select/recvfrom]...
close(3) = 0
对于域名:
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 3
close(3) = 0
似乎 PHP 甚至没有尝试对那个套接字做任何事情。或者甚至解决域,就此而言。怎么回事?
在有或没有 ipv6 支持的情况下重新编译 PHP 似乎并不重要。在这个系统上禁用 ipv6 是不可取的。
Gentoo Linux,PHP 5.3.14,目前正在尝试 PHP 5.4,看看是否有帮助。有人有想法吗?
编辑:
php -r 'echo gethostbyname("www.google.com");'
工作并产生一个 ipv4,而
php -r 'echo(file_get_contents("http://[2a00:1450:4007:803::1011]/"));'
似乎返回一个空白结果。
编辑2:
第一次我什至没有注意到,使用名称时打开的 v6 套接字是 SOCK_DGRAM。这是 PHP 试图解析域名吗?我尝试在 resolv.conf 中将解析器从 127.0.0.1 切换到 ::1,但没有帮助。