From: GOTO Kentaro Date: 2002-09-02T23:36:38+09:00 Subject: [ruby-dev:18153] Re: Selection IPv4/IPv6 at TCPSocket At Mon, 2 Sep 2002 20:26:11 +0900, NISHI Takao wrote: > > ちょっとした疑問なんですが、IPv4 と IPv6 のどちらを選ぶべきかの情報は > > 本来どこにあるんでしょう? > > ちゃんと確認したわけではありませんが,現状ではリゾルバとカーネル依存では > ないかと思います。 > USAGIカーネル+glibc2.2では,DNSにAAAAレコードがあり,カーネルがIPv6に対 > 応していればIPv6を選択するようになっているように見えます。 > FreeBSD 4.3でも同様です。 まあそんな感じですよね。 現行の文書だとRFC2553(Informational)を参考にするのが良いと思 いますが、どのプロトコルを使うかについて、サービス側から教え てくれる情報についての規定はないようです。 > > なんとなく、本来は DNS にそういう情報があって、自動的に選択されるべき > > な気がします。で、この話はなんらかの不具合によりそれがうまく動かない場 > > 合に対する手段を提供するというのが目的だと思うんですが、だとすると、そ > > の手段が IPv4 のハードコードをしやすい形だと、不具合のない環境で動かす > > のが厄介になりがちな気がします。 ハードコードに反対なのには同意しますが、不具合を避けるのが目 的なんでしょうか。その辺はよく分かりませんでした。例えば、プ ロトコルによって同じサービス名で異なる内容をサービスを提供す るサイトもあり得るので、そのような場合にはクライアント側でプ ロトコルを選択するしかない、というような状況を想定しているの かと思いました。いずれにせよ特殊な状況だとは思いますが。 > > プログラム本体は本来正しいやりかたで書き、付加的に不具合を避ける方法を > > Ruby に教えてやるというのがいいんじゃないかという気がするんですが。 > > (たとえば、このホストは IPv4 にしろとか。) 例えば Bind の gethostbyname() などは RES_OPTIONS なる環境変 数で挙動を変更することが出来るようです。これは RFC2133 に載っ ている RES_USE_INET6 という gethostbyname() のフラグを利用す る方法なのですが、実は RFC2553 obsoletes RFC2133 で、新版で ある RFC2553 にはこの方法を載っていません。RFC2133 から RFC2553 までの過程の議論を探して読めば、過渡的な運用に関する 考察が得らるのかも知れません。 > 現在のRubyではopen_inet()関数内で hints.ai_family = PF_UNSPEC;と常に自動 > 的にai_familyを選択するような実装がなされています。 > > しかしIPv4/IPv6のどちらを使うかを明示できないため,Aレコード,AAAAレコー > ドを共にもつホスト上で稼動しているものの,実際にはIPv4,IPv6のどちらかで > しかlistenしていないサービスにアクセスした場合,IPv6で接続に失敗したら > IPv4で(あるいはその逆で)と言う処理が困難となっています。 実際問題としてそんなに困難でしょうか? [ruby-dev:18133] に書 いたように getaddrinfo() でプロトコルファミリを指定してひい たアドレスで接続すれば出来ますよね。 ただし、武者さんが resolv.rb 云々といっていたので、 getaddrinfo() が resolv.rb にないことはマルチスレッドにした いときに困るかも知れません。 > これはIPv4->IPv6移行の過渡期的ならでは現象だと思いますので,田中さんのおっ > しゃるようにクラス新設という目立った方法ではなく,付加的な情報として扱う > 方が良いように思えます。 別の理由ですがクラスを分けるのは良くないという結論にいたりま した。TCPServer 加えて,UDPSocket#newとの対称性の点からも引数でAI_FAMILYを指定できる方が > うつくしいと思うのですが如何でしょうか? TCPSocket.new はすでに省略可能なオプションを2つも持っている ので対称ではないし、これ以上オプションを複雑にするのは美しい とは思えないばかりか、かなり使いにくいと思います。 > # わたしが投げたパッチはai_family引数のチェックをしていないのでアレです > # が(^^; 僕のスクリプト [ruby-dev:18133] も実は TCPSocket オブジェク トしか返さないものでした。一応 TCPSocket.new4 と new6 を定義 したものに書き換えました: http://www.notwork.org/~gotoken/ruby/p/as-is/tcpsocket-protocol-depend.rb -- Gotoken