1. 概要
この記事では、IPv6 によるマルチキャストの実現方法を Golang のサンプルコードで例示します。
2. はじめに
前回の記事 “IPv4 によるマルチキャスト” では、IPv4 によるマルチキャストの実現方法を Golang サンプルコードで例示しました。
今回の記事では、IPv6 によるマルチキャストを取り上げます。
なぜ、IPv4 ではなく、わざわざ IPv6 を利用するのか?
それは、ネットワーク設計の要件によっては、IPv6 のエニーキャストも、とても有用であるため、IPv6 のエニーキャストについて投稿する前に、IPv6 のマルチキャストの実現方法について取り上げました。
マルチキャスト、エニーキャスト、ユニキャスト、ブロードキャストなど、それぞれの意味については下記のリンクをご参照ください。
また、UDP やマルチキャストの有用性については、前回の記事 “IPv4 によるマルチキャスト” をご参照ください。
今回は、前回と同じように、マルチキャスト送信サーバー x 1、マルチキャスト受信サーバー x 2 のミニマム構成により、マルチキャストの実現方法を Golang サンプルコードで例示します。
3. 環境
- RHEL-7 系
- Go 1.9
4. 設計
- IPv6 マルチキャスト送信側 x 1
- sender1([ff02::1%eth0]:56789)
- IPv6 マルチキャスト受信側 x 2
- receiver1([ff02::1]:56789)
- receiver2([ff02::1]:56789)
5. IPv6 マルチキャストアドレス
IPv6 では、ff00::/8
ブロックにあるアドレスを、マルチキャストアドレスと呼びます。
そして、そのレンジにある ff02::/16
ブロックの IPv6 アドレスは、Link-Local マルチキャストアドレスといい、02
によりそのスコープを Link-Local に限定する事で、単一リンク内(単一サブネット内)に対してのマルチキャストを可能としています。
更に、ff02::1/128
アドレスの ::1
は、全ノードマルチキャストアドレスといい、対象マルチキャストグループの全ノードへのマルチキャストが可能となります。
(::2
は、全ルータマルチキャストアドレスといい、対象マルチキャストグループの全ルータへの配送が可能)
この記事では、ff02::1
のリンクローカルスコープの全ノードマルチキャストアドレスと 56789
ポートを例示に使用します。
6. Golang サンプルコード
@ sender1
$ sudo nvim ~/go/ipv6_multicast_sender.go
package main
import (
"fmt"
"net"
"strconv"
"time"
)
func main() {
ipv6 := "[ff02::1%eth0]"
port := ":56789"
addr := ipv6 + port
wait_time := 1
format := "Message "
fmt.Println("Sender:", addr)
conn, err := net.Dial("udp", addr)
_error(err)
defer conn.Close()
c := 0
for {
time.Sleep(time.Duration(wait_time) * time.Second)
message := format + strconv.Itoa(c)
conn.Write([]byte(message))
fmt.Printf("%s\n", message)
c++
}
}
func _error(_err error) {
if _err != nil {
panic(_err)
}
}
@ receiver1, 2
$ sudo nvim ~/go/ipv6_multicast_receiver.go
package main
import (
"fmt"
"net"
)
func main() {
ipv6 := "[ff02::1]"
port := ":56789"
addr := ipv6 + port
fmt.Println("Receiver:", addr)
udp_addr, err := net.ResolveUDPAddr("udp", addr)
_error(err)
listener, err := net.ListenMulticastUDP("udp", nil, udp_addr)
_error(err)
defer listener.Close()
buffer := make([]byte, 1240)
for {
length, remoteAddress, err := listener.ReadFrom(buffer)
_error(err)
fmt.Printf("Sender: %v\n", remoteAddress)
fmt.Printf("Contents: %s\n", string(buffer[:length]))
}
}
func _error(_err error) {
if _err != nil {
panic(_err)
}
}
7. Golang サンプル実行
@ receiver1, 2
$ sudo go run ~/go/ipv6_multicast_receiver.go
@ sender1
$ sudo go run ~/go/ipv6_multicast_sender.go
8. まとめ
この記事では、IPv6 によるマルチキャストの実現方法を Golang のサンプルコードで例示しました。
UDP マルチキャストは、効率的な死活監視設計や、自律ネットワーク設計、あるいは No Cluster データリソース設計など、要件や用途によっては有用な使い方が可能となりえます。
そして、IPv6 のエニーキャストも、ネットワーク設計の要件によってはとても有用であるため、IPv6 のエニーキャストについて投稿する前に、今回は IPv6 のマルチキャストの実現方法について取り上げました。