经过几个小时尝试调试遇到fopen()问题的第三方应用程序后,我终于发现了这一点
php -r 'echo(file_get_contents("http://www.google.com/robots.txt"));'
Run Code Online (Sandbox Code Playgroud)
失败了,但是
php -r 'echo(file_get_contents("http://173.194.32.81/robots.txt"));'
Run Code Online (Sandbox Code Playgroud)
成功.请注意,作为网络服务器用户,我可以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
Run Code Online (Sandbox Code Playgroud)
对于域名:
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 3
close(3) = 0
Run Code Online (Sandbox Code Playgroud)
似乎PHP甚至没有尝试对该套接字做任何事情.或者甚至解决域名问题.WTF?
使用或不使用ipv6支持重新编译PHP似乎并不重要.不希望在此系统上禁用ipv6.
Gentoo Linux,PHP 5.3.14,目前试用PHP 5.4并看看它是否有帮助.有人有想法吗?
编辑:
php -r 'echo gethostbyname("www.google.com");'
Run Code Online (Sandbox Code Playgroud)
工作并产生一个ipv4,而
php -r 'echo(file_get_contents("http://[2a00:1450:4007:803::1011]/"));'
Run Code Online (Sandbox Code Playgroud)
似乎返回空白结果.
编辑2:
我第一次没注意到,当使用名称时打开的v6套接字是SOCK_DGRAM.这个PHP试图解析域名吗?我尝试在resolv.conf中将我的解析器从127.0.0.1切换到:: 1,但它没有帮助.
GDB 表明那个神秘的未使用的套接字调用实际上来自 libcurl。我重新编译了没有 libcurl 的 php 并且它可以工作。我将继续调查原因,但到目前为止,解决方法似乎有效。