告知など
- 「勇者彼女がトイレから出てきません。」
- 彼女がうちのアパートに来たかと思ったらトイレに入って出てこなくて、 何をしているかというと、異世界で勇者をしている話。
- 「ダウン症があるとかないとかどうでもいい、誇りがあればいい。」
- そろそろ子育てエッセイなどというものを書いてみようかと思った次第。
- 「小説生成システム開発計画 - プロジェクトNUE」
- 計算機に小説、いや、使い物になる文章を作らせてみようという試みを、 勉強しながらやってます。
2009-11-06 [Fri]
▼ 自分のIPアドレスを得る方法
自分のIPアドレス、特に外部との通信に使えるアドレスを得る方法は、なかなか難しい。一般的には以下の手順が最もreasonableな方法であると言われている。
・ UDPのsocketを作る
・ どこか「遠くのアドレス」に向かってconnectする
・ getsocknameして自分側のアドレスを得る
つまり、どこか遠くに通信するためのソケットを用意し、その自分側のアドレスが外部と通信するためのアドレスとみなすという方法だ。UDPでconnectしてもパケットは流れないので、kernelのrouting tableに基づいてこのアドレスは決定される。
さて、この「遠くのアドレス」は何が良いだろうと思い、うーん、使ってなさそうな「10.1.1.1」にしてみたりすると、10.0.0.0/8という経路を裏口のインタフェースに持っていたりする環境ではまったりする。
ま、これはプライベートアドレスを使った僕が悪いということで。
おそらく、自分が管理している範囲で使っていないグローバルアドレスを指定するのが、最も適当だと思う。
しかし、上記の方法ではうまくいかない場合がある。それはdefault経路がない場合だ。こういった環境は、例えば社内LANなどで、外部との通信が同じセグメントにあるproxy(HTTPやSOCKSなど)を経由してのみ行われるので、defaultが必要ない環境などで実在する。
この場合は、仕方がないので自分のインタフェースを順番に調べて、付いているIPアドレスの中で適当そうなものを推測して使うしかない。だが、ここにもはまりポイントがあり、BSDだとgetifaddrs()があるのに、Linuxはない。したがって、getifaddrsの有無で処理を分けないといけない。
さらに、一つのインタフェースで複数のアドレスがついていた場合どうするか。例えばIPv6のlink localしかついていないインタフェースとglobal addressが付いているインタフェースがあったら、普通はglobal addressを使う。ということは、一旦全部のインタフェースを探索し、global addressがなかったら、再度探索して最初のlink localを使う、などとしないといけない(または、link localは最初から対象外にしてもいいかもしれないけど)。
という感じで、かなり面倒なので、「自分のIPアドレス」を必要とするアプリケーションは、アドレスを明示的に指定できるコマンドライン引数または設定ファイルを用意しておくことをお勧めする。多分それが一番はまらない。