10

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"));'

成功します。Webサーバーユーザーとして、www.google.comにpingを実行すると、問題なく解決されることに注意してください。

PHPの両方の実行をstraceしましたが、次のように分岐しています。

数値v4URLの場合:

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はそのソケットで何もしようとさえしなかったようです。または、ドメインを解決することもできます。WTF?

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に切り替えようとしましたが、役に立ちませんでした。

4

2 に答える 2

1

GDB は、謎の未使用のソケット呼び出しが実際には libcurl からのものであることを示しました。libcurlなしでphpを再コンパイルしましたが、動作します。原因の調査を続けますが、今のところ回避策は機能しているようです。

于 2012-07-01T22:11:08.597 に答える
0

これは、php の設定ではなく、オペレーティング システムの設定だと思います。IPv6 よりも IPv4 を優先するように /etc/gai.conf ファイルを編集する必要があると思います。ちょっとしたグーグル検索で、その方法を説明するこの記事が見つかりました。正直なところ、私はgai.confに詳しくないので、あなたのマイレージはさまざまかもしれませんが、ほとんどのシステムでは、1行のコメントを外すだけのようです.

SOCK_DGRAM が表示されている理由については、推測する必要がある場合は、DNS ルックアップが UDP であるためだと思います。これはおそらくトレースで表示されているものですが、最初のトレースではアドレスがキャッシュされている可能性が高いため、すぐにリモートサーバーへの TCP 接続 (DOCK_STREAM) を確立しました。

于 2012-07-01T21:14:00.357 に答える