挫折しました。障壁高し。
障壁1)RubyはIPv6に対応しているのか
ドキュメント化されている箇所を見出せないでいます。
Ruby開発者MLのアーカイブらしきところの議論で、Windows版については普通に入手できるRubyバイナリパッケージはIPv6非対応らしいことが判明しました(ruby-dev:34517からのスレッド)。Windows上でIPv6を使いたい人は、自分でRubyをビルドしてねということのようです。(その際、ソースの修正がいるような記述もありますが、未確認)
UNIX(Linux)についてはそこでも言及がなかったので不明です。
自宅PCのCentOS 5に含まれるruby 1.8.5では、IPv6アドレスを指定してUDPSocketのsendを呼ぶと"Address family not supported by protocol"となります。これは自分の書いたプログラムが悪いのかIPv6非対応なのか区別はつきませんが以下試したことをメモ。
require "socket" udp = UDPSocket.open() udp.send("HELLO", 0, "ff02::1234:1", 1234)
実行すると以下のようにエラーとなります。
sender.rb:13:in `send': Address family not supported by protocol - sendto(2) (Errno::EAFNOSUPPORT) from sender.rb:13 $ ruby --version ruby 1.8.5 (2006-08-25) [i386-linux]
sendがIPv4/IPv6中立な処理になっていないのか、IPv6が無効なためエラーとなっているのか、ここでは分かりません(たぶん後者かなと思う)。
障壁2)Rubyのソケット通信処理はC言語ソケットAPIの知識が必要
TCP/UDPのソケット通信プログラムを書くには、上記のとおりUNIXのBSDソケットAPIがそのまま出てきているので、実はC言語でのソケットAPIプログラミングの知識が前提です。
Rubyのリファレンスマニュアルも、C言語ソケットAPIの知識が前提で書かれています。例えばUDPSocket::sendの第2引数はflagsですが、これはmanでsend(2)を見てくださいというRubyリファレンスマニュアルの記述です。
send(mesg, flags[, dest_sockaddr])
send(mesg, flags, host, port)
ソケットを介してデータを送ります。flags に関しては send(2) を参照してください。connect していないソケットに対しては送り先を指定するため dest_sockaddr あるいは、host と port を指定する必要があります。実際に送ったデータの長さを返します。
上記のdest_sockaddrは、ソケットアドレス構造体(sockaddr_in)を意識した内容で、なにやら怪しげです(ソケットAPIの知識とRubyでのラップの仕方を知らないと・・・)。
マルチキャストの場合、さらにsetsockoptを使う必要があります。これも引数で指定するものはソケットAPIと同じです。
障壁3)IPv6対応のためのソケットAPIの使い方はちょっと違う
IPv4/IPv6決め打ちプログラミングにならないようにするには、昔流のソケットAPIの使い方ではなく、新しいソケットAPIの使い方が必要なので、ググって見かけるRubyのソケット通信プログラムではちょっと問題があります。このあたりの本に詳しく書かれています。
IPv6ネットワークプログラミング (network technology series)
- 作者: 萩野純一郎,小川彩子
- 出版社/メーカー: アスキー
- 発売日: 2003/02
- メディア: 単行本
- 購入: 2人 クリック: 66回
- この商品を含むブログ (29件) を見る