82
サンプルコードで理解する アプリケーションのIPv6対応 2015年2月28日 IPv6普及・高度化推進協議会 IPv4/IPv6共存WG アプリケーションのIPv6対応検討SWG 渡辺 露文(富士ソフト株式会社) (2015年3月9日資料更新) オープンソースカンファレンス 2015 Tokyo/Spring

20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

  • Upload
    v6app

  • View
    346

  • Download
    2

Embed Size (px)

Citation preview

Page 1: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

サンプルコードで理解する アプリケーションのIPv6対応

2015年2月28日

IPv6普及・高度化推進協議会 IPv4/IPv6共存WG アプリケーションのIPv6対応検討SWG

渡辺 露文(富士ソフト株式会社)

(2015年3月9日資料更新)

オープンソースカンファレンス 2015 Tokyo/Spring

Page 2: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

About me

渡辺 露文 (わたなべ つゆふみ) 富士ソフト株式会社 技術本部技術開発部

ネットワークエキスパート

業務経歴 1999年 富士ソフトABC株式会社(現 富士ソフト株式会社)入社 入社後、ISP、データセンター顧客向けシステムなどのシステム開

発・インフラ構築・運用、社内システムのインフラ企画・構築・運用に従事

2011年~ 技術調査および社内技術者教育に従事、2014年~ OSS社内利用管理も兼務

主な社外活動 IPv6普及・高度化推進協議会

– IPv4/IPv6共存WG アプリケーションのIPv6対応検討SWG – IPv4/IPv6共存WG IPv6導入に起因する問題検討SWG

技術評論社 Software Design にて「IPv6化の道も一歩から」連載(2012年12月号~2014年1月号;共同執筆)

< twatanab@fsi.co.jp >

- 1 -

Page 3: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Do you know …

IPv6 ?

- 2 -

Page 4: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Do you know …

IPv6 ? Internet Protocol version 6

インターネットの通信に関する規約(RFC791) IPネットワークに接続するには1つ以上のIPアドレスが必要 皆さんが馴染んでいるのはIPv4(例:10.1.2.3)

- 3 -

Page 5: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

こんなコード書いてないですよね?

このコード、イケてない…

use IO::Socket::IP; $host = “198.51.100.1”; : my $sock = IO::Socket::IP->new( PeerAddr => $host, PeerPort => $port, Proto => 'tcp' ) or die “Error: $!¥n”; :

- 4 -

Page 6: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

他にもイケてないコードがある

とある Androidプログラミング書籍に おけるソケット通信のサンプルコード

public class SocketEx… … … private final static String IP=“192.168.11.12”;//★変更必須

- 5 -

Page 7: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

他にもイケてないコードがある

とある Androidプログラミング書籍に おけるソケット通信のサンプルコード

public class SocketEx… … … private final static String IP=“192.168.11.12”;//★変更必須

良い子はマネしちゃダメ

- 6 -

Page 8: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

IPv6対応の話をする前に…

IPアドレスのハードコーディングはNG

ダメ。ゼッタイ。

$host = “www.example.com”

のようにFQDNで接続先を指定する

IPアドレス直書きすると、アドレス変更時に 修正が必要 再テストも必要

- 7 -

Page 9: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Internet

ネットワークアクセスの作法=名前解決を使う

Webアクセスの例

Client

Web Server

www.example.jp

192.0.2.1

権威DNS Server

198.51.100.53

①名前解決問合せ www.example.jp ?

②アドレス応答 www.example.jp ⇒ 192.0.2.1

③HTTP通信

FQDN

FQDNで接続先を指定し、DNSからアドレス取得

- 8 -

Page 10: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

なぜIPアドレス直書きがダメなのか?

アプリケーションは、IPアドレスに依存すべきではない

目的 変更・改修の理由

アプリケーション 機能の提供

業務要件の変更 サービス内容の変更 ユーザビリティ向上 …,etc.

インフラ 資源の提供

資源管理(IPアドレス、サーバリソース…)

性能

互いに変更の影響を受けるべきではない

同一システムでも変更・改修の理由・時期は異なる

例)IPアドレスでユーザを識別すべきではない

- 9 -

Page 11: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

いまどきのIPv6を知ろう!

- 10 -

Page 12: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

実はIPv6を使える環境が増えています①

最近のOS

Windows Vista以降

Mac OS X

Linux

FreeBSD

いずれも デフォルトで利用可能

- 11 -

Page 13: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

実はIPv6を使える環境が増えています②

インターネット回線

フレッツ光ネクスト

au ひかり

NURO 光

利用可能 既存ユーザへの 自動導入も進行中

すでに、ユーザからあなたのサービスにIPv6で アクセスされようとしている…かもしれない

- 12 -

Page 14: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

日本におけるIPv6の普及状況

フレッツ光ネクストのIPv6普及率(2014年9月)

IPv6普及率:3.9%

フレッツ光ネクスト契約数:15,805,000

au ひかりのIPv6普及率(2014年9月):99%

今後本格的に普及する前に IPv6対応を始めたほうが良い

出典:IPv6普及・高度化推進協議会 アクセス網におけるIPv6普及状況調査 http://v6pc.jp/jp/spread/ipv6spread_03.phtml

- 13 -

Page 15: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

余談:IPv6でインターネットにアクセスできるかの確認方法

Webブラウザで http://www.test-ipv6.jp にアクセス

Webブラウザで http://www.kame.net にアクセス

IPv6でアクセスすると、亀が踊ります♪

- 14 -

Page 16: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

IPv6の背景:IPv4アドレス枯渇

IPv4アドレスの在庫状況 (地域インターネットレジストリ)

通信事業者、ISP、 データセンター、

クラウド事業者等の在庫が残るのみ

世界的に足りなくなってきている

- 15 -

Page 17: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

もう少しIPv6を知ろう!

- 16 -

Page 18: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

IPv4とIPv6とでは何が違うのか?(1)

アドレス体系が異なる(IPv6のアドレス空間は広大)

IPv4)192.0.2.1

IPv6完全表記)2001:0db8:0000:0000:0001:0000:0000:0001

IPv6省略表記)2001:db8::1:0:0:1 (RFC5952準拠)

IPv4アドレス IPv6アドレス

アドレス長 32bit 128bit

文字列表記

表記法 8bitずつ区切り、10進数で表記

16bitずつ区切り、16進数で表記

区切り文字 . (ドット) : (コロン)

文字列長 15文字以内 39文字以内

- 17 -

Page 19: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

グローバルスコープ

IPv4とIPv6とでは何が違うのか?(2)

リンクローカルスコープ

リンクローカルアドレス fe80::/10

ユニークローカルアドレス fc00::/7

グローバルユニキャストアドレス 2000::/3

IPv6では1つのNICに複数のアドレスを 有効範囲に応じて割当て、使い分ける

- 18 -

Page 20: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

IPv4とIPv6の関係(1)

先ほど紹介したものの他にも機能的にIPv4と異なることがある

IPv4とIPv6は互換性がない

- 19 -

Page 21: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

IPv4とIPv6の接続性

Internet

IPv4対応

(IPv6非対応)

システム

IPv4/IPv6

両対応システム

IPv6対応

(IPv4非対応)

システム

(1) (2)

(3)

IPv4端末

IPv4/IPv6 両対応端末

IPv6端末

IPv4

IPv6

- 20 -

Page 22: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

IPv4とIPv6の関係(2)

両方に対応している環境では(デフォルトで)

IPv6 > IPv4

- 21 -

Page 23: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

IPv6に対応しない場合の影響

1. IPv6のみの環境と通信できない

ビジネス機会を損失する

システム連携が行えず要件を満たせなくなる

2. 今後、IPv4はサービスレベルが低下していく

通信事業者等によるCGN(Carrier Grade NAT)導入により、遅くなったり、利用できるセッション数が少なくなったりする可能性がある

IPv6に対応しなきゃ! - 22 -

Page 24: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

WebサービスのIPv6対応

ネットワークとサーバがIPv6に対応すれば、 IPv6で接続可能

接続は可能だが…

例えば

システム連携がうまくいかない

想定外の挙動をする

アプリケーションのIPv6対応が不可欠!

サービスが正常に動作しない かもしれない

- 23 -

Page 25: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

2. サンプルコードで理解しよう 1. C ソケットサーバ/クライアント

2. PHP ソケットクライアント

3. PHP Webアクセス履歴照会&集計

- 24 -

Page 26: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

アプリケーションIPv6対応の基本方針①

IPv6対応 = IPv4とIPv6の両方で動作する

シングルソースコードで対応

- 25 -

Page 27: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

アプリケーションのIPv6対応のポイント

Ethernet

IP(v4/v6)

TCP / UDP

アプリケーション

OS

ミドルウェア/ フレームワーク

アプリケーション

OS

フレームワーク

HTTP/HTTPS SMTP, SSH, ソケット通信など

クライアント サーバ

①IPv4/IPv6両対応の プログラミング言語と実行環境を使う

②通信処理をIPv4/IPv6の 両方に対応させる

③データとしてIPアドレスを 扱う箇所をIPv4/IPv6の 両方に対応させる

- 26 -

Page 28: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

ここでいうIPv4/IPv6両対応とは?

IPv4/IPv6両方のアドレスを適切に扱える

IPv4/IPv6両方で通信できる

これらを満たすプログラミング言語、実装環境を利用する

名前解決機構 格納領域

- 27 -

Page 29: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample 1 C ソケットサーバ/クライアント

萩野純一郎(itojun)氏の著書「IPv6ネットワーク プログラミング」に掲載されているソケット プログラム

詳細は↓

「アプリケーションのIPv6対応ガイドライン基礎編 添付資料」IPv6普及・高度化推進協議会 IPv4/IPv6共存WG アプリケーションのIPv6対応検討SWG http://www.v6pc.jp/jp/upload/pdf/socket-sample-20121203.pdf

- 28 -

Page 30: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample 1 どんなアプリ?

クライアント (IPv4/IPv6を問わず)任意の

ホスト、ポートに対してソケット 接続し、サーバのレスポンスを標 準出力へ出力

サーバ (IPv4/IPv6を問わず)任意のポートでソケット接続を待ち

受け、接続したクライアントに “Hello: 接続元IPアドレス” という文字列を送信

複数のソケットを生成する デュアルスタック対応 サーバプログラム

サーバ

プロセス

IPv6

IPv4

サーバ プログラム

起動

接続

接続

IPv6

IPv4

- 29 -

Page 31: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

ソケットプログラミングの流れ

- 30 -

Page 32: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

コーディングの留意点

関数、構造体はIPv4/IPv6両対応のものを使用する

アドレス情報は addrinfo 構造体や、それを利用するgetaddrinfo() 関数や getnameinfo() 関数を使用する

gethostbyname() 関数や getservbyname() 関数はIPv6非対応

getaddrinfo() 関数を使い、addrinfo 構造体のリストの形で相手先ホストのIPアドレス列を取得する

ソケットアドレスは sockaddr_storage 構造体を使用する

- 31 -

Page 33: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

クライアントプログラムのポイント

フォールバック:接続できない場合に別の接続先への接続に切替える動作

接続先アドレス情報をリストで取得し、順にたどる

Client

Web Server

www.example.jp

DNS Server

www.example.jp IN AAAA 2001:db8:100::1 www.example.jp IN A 192.0.2.1

①名前解決問合せ www.example.jp ?

②AAAA応答 2001:db8:100::1 A応答 192.0.2.1

③HTTP通信(IPv6) 2001:db8:100::1

192.0.2.1

2001:db8:ffff::1

198.51.100.1 ④HTTP通信(IPv4)

フォールバック

- 32 -

Page 34: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample1 コード解説(1)

クライアントプログラム(抜粋) ~snip~ int main(int argc, char **argv) { struct addrinfo hints, *res, *res0; ssize_t l; int s; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; char buf[1024]; int error; ~snip~

アドレス情報は addrinfo 構造体に格納

- 33 -

Page 35: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample1 コード解説(2)

クライアントプログラム(抜粋)その2 ~snip~ /* resolve address/port into sockaddr */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(argv[1], argv[2], &hints, &res0); if (error) { fprintf(stderr, "%s %s: %s¥n", argv[1], argv[2], gai_strerror(error)); exit(1); /*NOTREACHED*/ }

getaddrinfo()で、(接続先)アドレス情報を取得し、&res0にaddrinfo構造体

リストの先頭へのポインタが入る

- 34 -

Page 36: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample1 コード解説(3)

クライアントプログラム(抜粋)その3 /* try all the sockaddrs until connection goes successful */ for (res = res0; res; res = res->ai_next) { error = getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV); if (error) { fprintf(stderr, "%s %s: %s¥n", argv[1], argv[2], gai_strerror(error)); continue; } fprintf(stderr, "trying %s port %s¥n", hbuf, sbuf); s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s < 0) continue;

addrinfo構造体 リストをたどる

ホスト名を取得(逆引き)

Socket生成

- 35 -

Page 37: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample1 コード解説(4)

クライアントプログラム(抜粋)その4 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { close(s); s = -1; continue; } while ((l = read(s, buf, sizeof(buf))) > 0) write(STDOUT_FILENO, buf, l); close(s); exit(0); /*NOTREACHED*/ } fprintf(stderr, "test: no destination to connect to¥n"); exit(1); /*NOTREACHED*/ }

接続!

- 36 -

Page 38: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

クライアントプログラムのポイントおさらい

フォールバック:接続できない場合に別の接続先への接続に切替える動作 ⇒アドレスはリストで取得

Client

Web Server

www.example.jp

DNS Server

www.example.jp IN AAAA 2001:db8:100::1 www.example.jp IN A 192.0.2.1

①名前解決問合せ www.example.jp ?

②AAAA応答 2001:db8:100::1 A応答 192.0.2.1

③HTTP通信(IPv6) 2001:db8:100::1

192.0.2.1

2001:db8:ffff::1

198.51.100.1 ④HTTP通信(IPv4)

フォールバック

- 37 -

Page 39: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

ソケットサーバプログラミング

アルゴリズムは大きく分けて3種類

手法 利点 欠点

1 IPv4対応とIPv6対応の2プロセスを並行動作させる

アプリケーションの構成はシングルスタック構成のままでデュアルスタックに対応できる

複数プロセスで共有リソースを扱う場合、プロセス間で並行制御する必要がある

2 複数のsocketを生成するデーモンを作る

ひとつのプロセスでマルチプロトコルに対応できる

プログラムが複雑になる

3 inetdから呼び出し可能なサーバにする

通信部分をinetdが代行するため、通信のIPv6化を意識しなくてよい

inetdを必要とする

- 38 -

Page 40: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

複数のソケットを生成するデーモンを作る

接続の待受を並列化する必要がある

1. 単一アドレスを指定

2. Socket生成 3. Socketをアドレスに

bind 4. ポートをlisten

5. 接続待ちループ

① 接続要求受付 ② データ読み書き ③ 終了

1. アドレスリストを取得 2. 接続待ち開始ループ(アドレ

スリストを一巡)

3. 接続待ちループ

① Socket生成 ② Socketをアドレスにbind ③ ポートをlisten

① 接続先ファイルディスクリプタ(複数)選択

② 接続要求受付 ③ データ読み書き ④ 終了

シングルスタック 手法2

変更

- 39 -

Page 41: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

複数ソケットを生成するデーモンのフロー

1アドレスずつSocketを生成

待受アドレス リスト指定

Socket生成

bind

listen

START

接続要求 あり?

接続受付

データ読み書き

接続終了 アドレスリスト終了?

No Yes

あり なし

接続先ファイル ディスクリプタ (複数)選択

アドレスリストから 1アドレス抽出

- 40 -

Page 42: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample1 コード解説(5)

サーバプログラム(抜粋)その1 ~Snip~ #define MAXSOCK 20 int main(int argc, char **argv) { struct addrinfo hints, *res, *res0; int error; struct sockaddr_storage from; socklen_t fromlen; int ls; int s[MAXSOCK]; int smax; int sockmax; fd_set rfd, rfd0; int n; int i;

消費されるSocketの最大数を20と定義している。

システムがサポートするあらゆるプロトコルをサポートする情報保存バッファ

- 41 -

Page 43: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample1 コード解説(6)

サーバプログラム(抜粋)その2 char hbuf[NI_MAXHOST]; #ifdef IPV6_V6ONLY const int on = 1; #endif if (argc != 2) { fprintf(stderr, "usage: test port¥n"); exit(1); /*NOTREACHED*/ } memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_UNSPEC; error = getaddrinfo(NULL, argv[1], &hints, &res0);

IPV6_V6ONLYについては後述

全てのアドレスファミリを対象とする

OSがListen可能なプロトコル・アドレスのための addrinfoのリストが生成され、res0 に返される

- 42 -

Page 44: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample1 コード解説(7)

サーバプログラム(抜粋)その3 if (error) { fprintf(stderr, "%s: %s¥n", argv[1], gai_strerror(error)); exit(1); /*NOTREACHED*/ } smax = 0; sockmax = -1; for (res = res0; res && smax < MAXSOCK; res = res->ai_next) { s[smax] = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s[smax] < 0) continue;

得られた addrinfo すべてについて socket生成、

bind、listen を行う

- 43 -

Page 45: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample1 コード解説(8)

サーバプログラム(抜粋)その4 /* avoid FD_SET overrun */ if (s[smax] >= FD_SETSIZE) { close(s[smax]); s[smax] = -1; continue; } #ifdef IPV6_V6ONLY if (res->ai_family == AF_INET6 && setsockopt(s[smax], IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) { perror("setsockopt(IPV6_V6ONLY)"); close(s[smax]); s[smax] = -1; continue; } #endif

- 44 -

IPV6_V6ONLYマクロが扱える環境では、IPv4マップドアドレスに起因するセキュリティホールを防ぐため、ソケットのオプションに

IPV6_V6ONLY を設定する

Page 46: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample1 コード解説(9)

サーバプログラム(抜粋)その5 if (bind(s[smax], res->ai_addr, res->ai_addrlen) < 0) { close(s[smax]); s[smax] = -1; continue; } if (listen(s[smax], 5) < 0) { close(s[smax]); s[smax] = -1; continue; } if (s[smax] > sockmax) sockmax = s[smax]; smax++; }

- 45 -

Page 47: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample1 コード解説(10)

サーバプログラム(抜粋)その6 if (smax == 0) { fprintf(stderr, "test: no socket to listen to¥n"); exit(1); /*NOTREACHED*/ } FD_ZERO(&rfd0); for (i = 0; i < smax; i++) FD_SET(s[i], &rfd0); while (1) { rfd = rfd0; n = select(sockmax + 1, &rfd, NULL, NULL, NULL); if (n < 0) { perror("select"); exit(1); /*NOTREACHED*/ }

Select関数で複数デスクリプタを待つ

- 46 -

Page 48: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample1 コード解説(11)

サーバプログラム(抜粋)その7 for (i = 0; i < smax; i++) { if (FD_ISSET(s[i], &rfd)) { fromlen = sizeof(from); ls = accept(s[i], (struct sockaddr *)&from, &fromlen); if (ls < 0) continue; error = getnameinfo( (struct sockaddr *)&from, fromlen, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST); if (error) { exit(1); /*NOTREACHED*/ }

セットされているファイルデスクリプタを accept

getnameinfo() で、 接続元の情報を取得

- 47 -

Page 49: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample1 コード解説(12)

サーバプログラム(抜粋)その8 write(ls, "hello ", 6); write(ls, hbuf, strlen(hbuf)); write(ls, "¥n", 1); close(ls); } } } /*NOTREACHED*/ }

接続されたファイルデスクリプタに write()

- 48 -

Page 50: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample 2 ソケットクライアントWebアプリ (PHP)

- 49 -

Page 51: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample2 どんなアプリ?

フォームから入力されたホスト、ポートに対してソケット接続を行い、サーバ側の出力をそのままWebページに出力

- 50 -

Page 52: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

コーディングの留意点

関数、データ型はIPv4/IPv6両対応のものを使用 する

データ型:文字列型

関数:

get_dns_record()

– gethostbyname() はIPv6非対応

gethostbyaddr()

ライブラリ、フィルタを用いて入力値検証、変換

ライブラリ:Net_IPv6

フィルタ:FILTER_VALIDATE_IP

- 51 -

Page 53: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample2 処理フロー

- 52 -

ユーザ入力値から 接続先アドレス(リスト)を

取得

接続先アドレス(リスト)に、順にソケットを生成して接続

Page 54: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample2 コード解説(1)

<?php $IS_DEBUG = 0; $host = filter_input(INPUT_GET, 'host'); $port = filter_input(INPUT_GET, 'port', FILTER_VALIDATE_INT); if ($host && $port){ $addresses = array(); if ($host_addr = filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)){ $addresses[0]['domain'] = AF_INET6; $addresses[0]['address'] = $host_addr; } elseif ($host_addr = filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)){ $addresses[0]['domain'] = AF_INET; $addresses[0]['address'] = $host_addr; フィルタを用いて変数がIPv6/IPv4 アドレスか判断 アドレスからプロトコルに応じたプロトコルファミリを設定

- 53 -

Page 55: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample2 コード解説(2)

} else { $host_list = dns_get_record($host); $size = sizeof($host_list); for ($loopcnt = 0; $loopcnt < $size; $loopcnt++){ if ($host_list[$loopcnt]['type'] === 'AAAA'){ $addresses[$loopcnt]['domain'] = AF_INET6; $addresses[$loopcnt]['address'] = $host_list[$loopcnt]['ipv6']; } else { $addresses[$loopcnt]['domain'] = AF_INET; $addresses[$loopcnt]['address'] = $host_list[$loopcnt]['ip']; } } } $size = sizeof($addresses); $message = "接続先ホスト名 " . $host . " ポート番号 " . $port . "<BR>¥n";

ホスト名の場合にはDNSからアドレスをリストで取得

リストの数だけ、アドレスを取得し接続先候補とする IPv6 は AAAA レコード、IPv4 は A レコードに格納

gethostbyname()は、IPv6非対応

- 54 -

Page 56: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample2 コード解説(3)

$connect_flag = 0; for ($loopcnt = 0; $loopcnt < $size && $connect_flag === 0; $loopcnt++){ if (($socket = socket_create($addresses[$loopcnt]['domain'], SOCK_STREAM, SOL_TCP)) === FALSE){ $error_code = socket_last_error(); $error_msg = socket_strerror($error_code); $message .= "connect to " . $addresses[$loopcnt]['address'] . "<BR>¥n"; $message .= 'socket create error: [' . $error_code . '] ' . $error_msg . "<BR>¥n"; } else { $message .= 'socket connect (' . ($loopcnt +1) . ') : ' . $addresses[$loopcnt]['address'] . " port: " . $port . "<BR>¥n";

- 55 -

ソケット作る

Page 57: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample2 コード解説(4)

if (socket_connect($socket, $addresses[$loopcnt]['address'], $port)){ $connect_flag = 1; $response = socket_read($socket, 1024); $message .= "サーバからのメッセージ:" . '<div style="margin: 10px">' . $response . '</div>' . "<BR>¥n"; } else { $error_code = socket_last_error(); $error_msg = socket_strerror($error_code); $message .= 'socket connect error: [' . $error_code . '] ' . $error_msg . "<BR>¥n"; } socket_close($socket); } } } else { $message = "接続先ホスト名 " . $host . " もしくはポート番号 " . $port . "が入力されていません"; } ?> - 56 -

接続する

切断する

Page 58: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample2 コード解説(5)

<html> <head> <meta charset="UTF-8"> <title>Socket通信クライアント(デュアルスタック版)</title> </head> <body> <H1>Socket通信クライアント(デュアルスタック版)</H1> <form action="<?php echo filter_input(INPUT_SERVER, 'PHP_SELF', FILTER_SANITIZE_URL)?>" method="GET"> 接続先ホスト <input type='text' name='host' value='<?php echo $host; ?>'> ポート番号 <input type='text' name='port'value='<?php echo $port; ?>'> <input type="submit" value="実行する"> </form> <HR> <?php echo $message; ?> </body> </html> - 57 -

Page 59: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample3 アクセス履歴表示・集計Webアプリ(PHP)

- 58 -

Page 60: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

サンプルアプリ3:アクセス履歴照会&集計 (PHP)

- 59 -

Page 61: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

データとしてIPアドレスを扱う箇所

入力 出力

整列

検索

格納

- 60 -

Page 62: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Webフォームからの入力

入力値の検証

IPアドレスを扱う場合、入力された文字列がIPアドレスとして取りうる値であることを検証

IPv4アドレス、IPv6アドレス いずれかとして取りうる値

2箇所で実施可能

ブラウザ側(HTML5のForm Validation等)

サーバ側

アドレス処理ライブラリ、フィルタを利用すると便利

例)PHP Net_IPv6::checkIPv6(); (PEARにて提供されるNet_IPv6パッケージに含まれる)

- 61 -

Page 63: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

格納、検索、整列、出力のポイント

IPアドレス型が定義されている場合は、IPアドレス型を使う 例) PostgreSQLのネットワークアドレス型

IPアドレス型が定義されていない場合は、文字列型で完全表記を使う IPv6完全表記)

2001:0db8:0000:0000:0001:0000:0000:0001 見やすさを求めるときは、省略表記(RFC5952準拠)で出力

過去に開発されたシステム・ツールでは、RFC5952に準拠しない省略表記が存在しうるので要注意

省略表記で扱うと、整列、検索時に不具合が出やすい

既存システムは、格納領域にIPv6アドレスが収まるかをチェック

- 62 -

Page 64: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

PostgreSQLのネットワークアドレス型

- 63 -

Page 65: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

コーディングの留意点

関数、データ型はIPv4/IPv6両対応のものを使用 する

データ型:文字列型

関数:

get_dns_record()

– gethostbyname() はIPv6非対応

gethostbyaddr()

ライブラリ、フィルタを用いて入力値検証、変換

ライブラリ:Net_IPv6

フィルタ:FILTER_VALIDATE_IP

- 64 -

Page 66: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample2 処理フロー

履歴書込み 履歴一覧表示・集計

- 65 -

接続元アドレスを取得

DBにレコード追加(INSERT)

格納先のDBのデータ型が文字列の場合は、省略表

記を完全表記に展開

ユーザ入力値から整列キー、昇順/降順、集計

フラグを取得

ユーザ入力値に従い、DBから履歴を読み込み、昇順/降順、集計して表示

Page 67: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample3 コード解説(1)

<?php require_once 'settings.php'; require_once 'modules.php'; $now = date('Y/m/d H:i:s'); $array_access = array ( 'source_addr' => filter_input(INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP), 'source_port' => filter_input(INPUT_SERVER, 'REMOTE_PORT', FILTER_VALIDATE_INT), 'server_addr' => filter_input(INPUT_SERVER, 'SERVER_ADDR', FILTER_VALIDATE_IP), 'access_time' => $now, ); $logging = write_history($array_access);

index.php

filter_input() でユーザ入力値がIPアドレス形式である

ことを検証

関数化したアクセス履歴書込みを呼び出し

- 66 -

Page 68: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample3 コード解説(2)

$sort_mode = array ( 'key' => filter_input(INPUT_GET, 'sort_key', FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => '/(^access_date$|^source_addr$|^source_port$|^count$)/'))), 'desc' => filter_input(INPUT_GET, 'desc', FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => '/(^desc$|^asc$)/'))), 'count' => filter_input(INPUT_GET, 'count', FILTER_VALIDATE_INT, array('options' => array('min_range' => 0, 'max_range' => 1))), ); if (!$sort_mode['key']){ $sort_mode['key'] = 'access_date'; } $history = display_history($sort_mode); ?> ~以下、HTML部分につき割愛~

index.php

関数化したアクセス履歴表示を呼び出し

- 67 -

Page 69: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample3 コード解説(3)

<?php // ////////////////////////// // 履歴書込み関数 function write_history ($array_access) { global $DSN; // ========================================== // DBのデータ型がvarcharの場合には、省略表記を完全表記に展開 // ========================================== if (constant('STORE_TYPE') !== 'INET') { require_once 'Net/IPv6.php'; if (Net_IPv6::checkIPv6($array_access['source_addr'])) { $source_addr = Net_IPv6::uncompress($array_access['source_addr'], TRUE); } else { $source_addr = $array_access['source_addr']; } }

modules.php

Net_IPv6::checkIPv6() で変数がIPv6アドレスである

ことを検証

省略表記を完全表記に展開(第2引数をTRUEにすることで

完全表記)

STORE_TYPE は、このプログラムで独自に定義

- 68 -

Page 70: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample3 コード解説(4)

$query = 'INSERT INTO access_history ( access_date, source_addr, source_port) VALUES (now(), :ip, :port)'; if ($dbh = new PDO($DSN)) { $sth = $dbh->prepare($query); $sth->execute(array(':ip' => $array_access['source_addr'], ':port' => $array_access['source_port'])); $err_code = $sth->errorCode(); if ($err_code === '00000'){ return OK; } else { return WRITE_ERROR; } } else { echo "DB connection error"; return OPEN_ERROR; } }

modules.php

- 69 -

Page 71: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample3 コード解説(5)

// ///////////////////////// // 履歴表示&アクセス数集計関数 function display_history ($sort_mode) { global $DSN; if ($sort_mode['count']){ // 集計時のクエリ作成 $query = 'SELECT source_addr, count(source_addr) FROM access_history GROUP BY source_addr'; if ($sort_mode['key'] === 'source_addr' || $sort_mode['key'] === 'count' ){ $query .= ' ORDER BY ' . $sort_mode['key']; if ($sort_mode['desc']) { $query .= ' ' . $sort_mode['desc']; } }

modules.php

整列時の指定は、 通常のSQL(ORDER

BY キー)

- 70 -

Page 72: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample3 コード解説(6)

} else { // 履歴一覧時のクエリー作成 $query = 'SELECT * FROM access_history'; if ($sort_mode['key'] && $sort_mode['key'] !== 'count' ){ $query .= ' ORDER BY ' . $sort_mode['key']; if ($sort_mode['desc']) { $query .= ' ' . $sort_mode['desc']; } $query .= ' NULLS LAST'; } }

modules.php

整列時の指定は、 通常のSQL(ORDER

BY キー)

- 71 -

Page 73: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample3 コード解説(7)

// ================================================= // DB接続&クエリ実行 // ================================================= $dbh = new PDO($DSN); if ($dbh) { $sth = $dbh->prepare($query); $sth->execute(); $result = $sth->fetchAll(); $sth->errorCode(); } else { echo "DB connection error"; }

modules.php

- 72 -

Page 74: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample3 コード解説(8)

// ================================================= // 出力整形 // ================================================= if (constant('STORE_TYPE') !== 'INET') { // 文字列で格納されている場合は、省略表記にするためにライブラリを呼び出す require_once 'Net/IPv6.php'; } if ($sort_mode['count']) { $ret_string = '<H2>アクセス集計</H2><TABLE border="1"><TR><TH>No.</TH><TH>接続元アドレス</TH><TH>接続回数</TH></TR>'; $size = sizeof($result); for ($loopcnt = 0; $loopcnt < $size; $loopcnt++){

modules.php

- 73 -

Page 75: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample3 コード解説(9)

if (constant('STORE_TYPE') !== 'INET') { // 文字列で格納されている場合は、省略表記にする if (Net_IPv6::checkIPv6($result[$loopcnt]['source_addr'])){ $source_addr = Net_IPv6::compress($result[$loopcnt]['source_addr']); } else { $source_addr = $result[$loopcnt]['source_addr']; } } else { $source_addr = $result[$loopcnt]['source_addr']; } $ret_string .= "<TR><TD align='right'>" . ($loopcnt +1) . "</TD><TD>" . $source_addr . "</TD><TD align='right'>" . $result[$loopcnt]['count'] . "</TD></TR>¥n"; } $ret_string .= '</TABLE>';

modules.php

完全表記を省略表記に

変換 (見やすさ

重視)

- 74 -

Page 76: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample3 コード解説(10)

} else { $ret_string = '<H2>アクセス履歴</H2><TABLE border="1"><TR><TH>No.</TH><TH>接続日時</TH><TH>接続元アドレス</TH><TH>接続元ポート番号</TH></TR>'; $size = sizeof($result); for ($loopcnt = 0; $loopcnt < $size; $loopcnt++){ if (constant('STORE_TYPE') !== 'INET') { // 文字列で格納されている場合は、省略表記にする if (Net_IPv6::checkIPv6($result[$loopcnt]['source_addr'])){ $source_addr = Net_IPv6::compress($result[$loopcnt]['source_addr']); } else { $source_addr = $result[$loopcnt]['source_addr']; } } else { $source_addr = $result[$loopcnt]['source_addr']; }

modules.php

完全表記を省略表記に

変換 (見やすさ

重視)

- 75 -

Page 77: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

Sample3 コード解説(10)

$ret_string .= "<TR><TD align='right'>" . ($loopcnt +1) . "</TD><TD>" . $result[$loopcnt]['access_date'] . "</TD><TD>" . $source_addr . "</TD><TD align='right'>" . $result[$loopcnt]['source_port'] . "</TD></TR>¥n"; } $ret_string .= '</TABLE>'; } return $ret_string; } ?>

modules.php

- 76 -

Page 78: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

おわりに

- 77 -

Page 79: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

まとめ①

IPv6を使える環境が増えている

IPv4とIPv6は互換性なし

WebサービスのIPv6対応にはアプリケーションの対応が不可欠

IPアドレスのハードコーディングは ダメ。ゼッタイ。

- 78 -

Page 80: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

まとめ②

アプリケーションのIPv6対応の基本方針

IPv6対応=IPv6/IPv4の両方で動作させること

シングルソースコードで対応する

アプリケーションのIPv6対応のポイント

1. IPv4/IPv6両対応のプログラミング言語と実行環境を使う

2. 通信処理をIPv4/IPv6の両方に対応させる

3. データとしてIPアドレスを扱う箇所をIPv4/IPv6の両方に 対応させる

決して難しくない! 今日から開発するアプリケーションはIPv6に対応させよう!

- 79 -

Page 81: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

つづきはWebで(参考文献)

「アプリケーションのIPv6対応ガイドライン 基礎編」/IPv6普及・高度化推進協議会 IPv4/IPv6共存WG アプリケーションのIPv6対応検討SWG http://www.v6pc.jp/jp/entry/wg/2012/12/ipv610.p

html

「アプリケーションのIPv6対応ガイドライン Webアプリ編(案)」/IPv6普及・高度化推進協議会 IPv4/IPv6共存WG アプリケーションのIPv6対応検討SWG http://www.v6pc.jp/jp/entry/wg/2014/06/ipv6web

.phtml

- 80 -

Page 82: 20150228 OSC2015 Tokyo/Spring サンプルコードで理解するアプリケーションのIPv6対応

Copyright ©2015 FUJISOFT INCORPORATED, All rights reserved.

ご清聴いただき、 ありがとうございました

- 81 -