From: Jun-ichiro itojun Hagino Date: 1999-04-14T22:03:12+09:00 Subject: [ruby-list:13740] Re: IPv6 ruby >> 直したです。19990414aというやつはちゃんと動くはず。 >どうもです。えっと、動くんですけど、ダイナミックリンクだと >動きませんね。ぼくはよくわからないのですが、socket.so を >作るときに getaddrinfo/getnameinfo の入ったライブラリを >リンクしてやる必要があるということでしょう。モノはできてる >みたいなのであとは extconf.rb の書き方ですね(たぶん)。 はい。 >といっても僕もこういう状況での書き方は知りません。 README.v6に書いておいたのですが、現状 - KAME IPv6 stackの場合、/usr/local/v6/lib/libinet6.aというので getaddrinfo/getnameinfoを提供していますが、dynamic link libraryは 提供しておりません。さて、extconf.rbはどうすればいい? - 他のIPv6 stackも似たりよったりです。 - IPv4 only hostの場合、missing/getaddrinfo.cとかが使われますが、 これをsocket.soに入れるにはどうすればいいのか? - 両者の場合分けを解決するには? ext/socket/extconf.rb.in? というかんじです。 短期的解決: - ruby本体内からgetaddrinfoとgetnameinfoを一度でも参照しておけばよい。 例えば、void *p = (void *)getaddrinfo; とでも書けば勝ち。 ちょとずるいけど。 長期的解決: - libcにgetaddrinfoが入ればとりあえず解決するはずです。 bind 8.2に入ったので(動かないけど)、そのうち蔓延するのではないかと。 >> getaddrinfo/getnameinfoはとてもよいライブラリ関数だと思うので >> ぜひ皆さんに知ってほしいです。IPv4 onlyのときでも、socketまわりの >> プログラミングがとても楽ちんになります。see RFC2553. >TCP しか使ったことないのでいまひとつご利益がわかりませんが、 >楽ちんになる状況の簡単な例はありますか?? 例えば、こんなもんでいかがでしょう。 - AF_INETを一切hardcodeしなくてよい - IPPROTO_TCPもhardcodeしなくてよい(SOCK_STREAMだけ) - DNS database上に複数アドレスが書いてある場合の処理を書くのに ひじょーに快調 しかもAF_INETとAF_INET6が混ざってもok - struct in_addr (例えばsin->sin_addr)を一切手でいじらなくて済む gethostby*()系はみなstruct in_addrでアドレスを返してくるくせに、 connect()とかではstruct sockaddr_inが要求されていて 悲しかったのですが、getaddrinfo()を使えばstruct sockaddr_inが 返るので楽勝。 - さらに、inet_ptonとかinet_atonとも綺麗さっぱりお別れできる getaddrinfoとgetnameinfoだけあれば生きていけます。 itojun --- main() { struct addrinfo hints, *res0, *res; int error; int s; char *host = "www.kame.net"; char *port = "http"; char *failed = "?"; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(host, port, &hints, &res0); if (error) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error)); exit(1); } for (res = res0; res; res = res->ai_next) { s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s < 0) { failed = "socket"; continue; } if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { failed = "connect"; close(s); continue; } /* successful, some data transfer */ close(s); break; } if (!res) { perror(failed); freeaddrinfo(res0); exit(1); } fprintf(stderr, "successful\n"); freeaddrinfo(res0); exit(0); }