3
5

More than 5 years have passed since last update.

IPv6 によるマルチキャスト

Last updated at Posted at 2018-12-23

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

~/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

~/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 のマルチキャストの実現方法について取り上げました。

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5