前半では、TCP/IPのプログラミングをIPv4/v6のデュアルスタック、
Windows/Linuxで動作という視点で解説しました。
後半では、前半で触れなかったTCPが単なるバイトストリームであることに
注意をしてアプリケーションプロトコルを作ることにします。
またUDPのプログラムについても解説します。
開発環境は前半と同じです。
プログラミングを始める前に、IPv6についてついて少し解説します。
1.アドレスの数
128ビットで表されます(IPv4は23ビット)
いったいどれくらいの数かと言うと地球上にばらまくと1㎠あたり2.2×10^20
人類全員で分けると1人あたり4.9×10^28を持つことができます!。
2.アドレスの表記方法
16ビットごとにコロン「:」で区切り16進数で表記します。
例
FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF
ブロック内の上位の「0」を省略できます。
例
2001:0000:0000:0000:0012:34FF:EF56:789Aは
2001::12:34FF:EF56:789Aと書くことができます。
3.アドレスの種類
ユニキャストアドレス(Unicast Address)
同じIPアドレスを持つインターフェースは1つだけ存在します。
ユニキャストアドレスを宛先として送付されたパケットはそのアドレスの
唯一のインターフェースに届けられます。(IPv4と同じです)
マルチキャストアドレス(Multicast Address)
同じアドレスを持つ複数のインターフェースが存在します。
マルチキャストアドレスを宛先として送付されたパケットは、そのすべての
インターフェースに届けられます。(IPv4と同じです)
エニーキャストアドレス(Anycast Address)
同じアドレスを持つ複数のインターフェースが存在します。
エニーキャストアドレスを宛先として送付されたパケットは、そのいずれかの
インターフェースに届けられます。(IPv4にはありません)
3.アドレスタイプ スコープ
インターフェースローカル
あるノード上のひとつのインターフェースの範囲でのみ有効
マルチキャストで使用します。
リンクローカル
ある特定のリンク内でのみ有効
グローバル
有効範囲に制限がない
こんな感じです。/の後ろの数はプレフィックス長(IPv4と同じ考え方です)
0.未定義
::/128
1.ループバック
::1/128
2.マルチキャストアドレス
FF00::/8
3.リンクローカルユニキャストアドレス
FE80::/10
4.グローバルユニキャストアドレス
0.-3.以外
マルチキャストアドレスについて
先頭の8ビットがFF(1111 1111)から始まります。
FFの次の4ビットはフラグで
0: 永続的
1: 一時的
その次の4ビットはスコープで
2: リンクローカル 同じリンク上の全てのノードに送信
8: 組織ローカル 同じ拠点内の全てのノードに送信
E: グローバル
最後の112ビットはグループIDです
永続的なグループIDの例(1、2、101)
リンクローカル全ノード FF02::1
リンクローカル全ルータ FF02::2
リンクローカルNTPサーバ FF02::101
リンクローカルユニキャストアドレスについて
先頭10ビットが1111 1110 10
次の54ビットが0
インターフェースIDが64ビット
例
fe80::581c:f2d9:e72f:9b7a/64
グローバルユニキャストアドレスについて
現在IANAが割り振っているものはプレフィックス長64で次のような構造です
先頭3ビット001
グローバルプレフィックスが48ビット(先頭3ビットを含む)
サブネットが16ビット
インターフェースIDが64ビット
例
2001:ce8:132:4332:7819:7fb2:1ef9:f59/64
同一リンク内(オンリンク)にあるインターフェースのMACアドレスはIPv4では
学習結果(これまでに通信をした相手)をarpテーブルに格納しています。
IPv6では近隣キャッシュに格納されています。
近隣キャッシュの表示には
Linuxでは次のコマンドを使います。(devでインターフェースを指定します)
ip -6 nei show dev eth0
Windowsでは次のコマンドを使います。(最後の数字でインターフェースを指定します)
netsh interface ipv6 show neighbors 7
どのインターフェースを使うかは前半で作成したEnumInterface(Win, Linux)を使って一覧から
選択してください。指定しないとすべてのインターフェースに関する情報が
表示されてしまい煩雑です。
【Linux】 pi@shimodaPi1:~ $ ip -6 nei show dev eth0 2001:ce8:132:4332:a612:42ff:fe49:21c lladdr a4:12:42:49:02:1c router STALE fe80::a612:42ff:fe49:21c lladdr a4:12:42:49:02:1c router STALE
【Windows】 C:\Users\USER>netsh interface ipv6 show neighbors 7 インターフェイス 7: イーサネット インターネット アドレス 物理アドレス 種類 ——————————————– —————– ———– 2001:ce8:132:4332:a612:42ff:fe49:21c a4-12-42-49-02-1c 到達可能 (ルーター) fe80::a612:42ff:fe49:21c a4-12-42-49-02-1c 到達可能 (ルーター) ff02::1 33-33-00-00-00-01 恒久 ff02::2 33-33-00-00-00-02 恒久 ff02::c 33-33-00-00-00-0c 恒久 ff02::16 33-33-00-00-00-16 恒久 ff02::fb 33-33-00-00-00-fb 恒久 ff02::1:2 33-33-00-01-00-02 恒久 ff02::1:3 33-33-00-01-00-03 恒久 ff02::1:ff21:3e08 33-33-ff-21-3e-08 恒久 ff02::1:ff49:21c 33-33-ff-49-02-1c 恒久 ff02::1:ff75:1c54
近隣キャッシュには学習結果(これまでに通信した相手)しか格納されていません。
そこでリンクローカル全ノードマルチキャストアドレスに対してpingを実施して
テーブルを更新してみましょう。
Linuxでは次のようにします(-Iでインターフェースを指定します)
ping6 -I eth0 ff02::1
Windowsでは次のようにします(%7でインターフェースを指定します)
ping ff02::1%7
Windowsの場合、pingの応答は取れませんがちゃんとテーブルは更新されます。
どのインターフェースを使うかは前半で作成したEnumInterface(Win, Linux)を使って一覧から
選択してください。
【Linux】 pi@shimodaPi1:~ $ ip -6 nei show dev eth0 fe80::11a0:ecd4:2cf8:6e5c lladdr b8:27:eb:92:5a:bf REACHABLE fe80::1089:dd54:6dcc:4c5 lladdr 1c:1a:c0:8f:17:4e REACHABLE fe80::22b7:80ff:fec1:c903 lladdr 20:b7:80:c1:c9:03 REACHABLE fe80::14ef:59b4:207d:e7f3 lladdr c4:b3:01:ba:0a:5d REACHABLE fe80::1c5b:4d8c:495e:5235 lladdr c8:69:cd:3b:e2:b5 REACHABLE 2001:ce8:132:4332:a612:42ff:fe49:21c lladdr a4:12:42:49:02:1c router STALE fe80::461:d6b2:1801:f4cb lladdr c0:a5:3e:54:f7:5c REACHABLE fe80::86d:4304:b23c:86a5 lladdr 40:6c:8f:36:d8:6b REACHABLE fe80::a612:42ff:fe49:21c lladdr a4:12:42:49:02:1c router REACHABLE
【Windows】 C:\Users\USER>netsh interface ipv6 show neighbors 7 インターフェイス 7: イーサネット インターネット アドレス 物理アドレス 種類 ——————————————– —————– ———– 2001:ce8:132:4332:a612:42ff:fe49:21c a4-12-42-49-02-1c Stale (ルーター) fe80::461:d6b2:1801:f4cb c0-a5-3e-54-f7-5c 到達可能 fe80::86d:4304:b23c:86a5 40-6c-8f-36-d8-6b 到達可能 fe80::1089:dd54:6dcc:4c5 1c-1a-c0-8f-17-4e 到達可能 fe80::11a0:ecd4:2cf8:6e5c b8-27-eb-92-5a-bf 到達可能 fe80::14ef:59b4:207d:e7f3 c4-b3-01-ba-0a-5d 到達可能 fe80::183b:bce8:82c5:dab3 6c-19-c0-51-8d-4b 到達可能 fe80::1c5b:4d8c:495e:5235 c8-69-cd-3b-e2-b5 到達可能 fe80::22b7:80ff:fec1:c903 20-b7-80-c1-c9-03 到達可能 fe80::581c:f2d9:e72f:9b7a b8-27-eb-c7-0f-ea 到達可能 fe80::a612:42ff:fe49:21c a4-12-42-49-02-1c 到達可能 (ルーター) ff02::1 33-33-00-00-00-01 恒久 ff02::2 33-33-00-00-00-02 恒久 ff02::c 33-33-00-00-00-0c 恒久 ff02::16 33-33-00-00-00-16 恒久 ff02::fb 33-33-00-00-00-fb 恒久 ff02::1:2 33-33-00-01-00-02 恒久 ff02::1:3 33-33-00-01-00-03 恒久 ff02::1:ff21:3e08 33-33-ff-21-3e-08 恒久 ff02::1:ff49:21c 33-33-ff-49-02-1c 恒久 ff02::1:ff4c:799e 33-33-ff-4c-79-9e 恒久 ff02::1:ff75:1c54 33-33-ff-75-1c-54 恒久
オンリンク(同一リンク)にあるノードのMACアドレス一覧をとれますね。
(*)ip -4 nei show dev eth0, netsh interface ipv4 show neighbors 7を
実行するとarpテーブルの情報が得られます。
【コラム】
ネットワーク関係のコマンドのソースを見るとプログラムのヒントが満載です。
RaspberryPi(Linux)のコマンドのソースの取得方法
1./etc/apt/sources.listのdeb-srcのコメントを解除
2.apt-get updateを実施
これでソースを取得できるようになります
3. whichコマンド でコマンドの格納先を調べる
which ping
4.dpkg –search 格納先 でパッケージを調べる
dpkg –search /bin/ping
5.apt-get source パッケージでソースを取得
apt-get source iputils-ping