IPv4 によるマルチキャスト


1. 概要

この記事では、IPv4 によるマルチキャスト実現のための Golang のサンプルコードを投稿します。

2. はじめに

UDP は、信頼性、順序性、完全性は保証されないものの、処理コストが削減できることなどから用途によってはとても有用です。
例えば一般的には、UDP によるマルチキャストは、動画、音声、画像などのストリーム配信や、オンラインゲーム、SNMP、NTP、DNS などでよく利用されています。
また、コンピュータの死活監視制御においては、TCP 通信による監視対象ノードからのレスポンスの監視よりも、UDP 通信による監視対象ノードからの一方的なデータ送信の監視の方が、はるかに効率的に生存確認をする事が可能な場合があります。
更には、これをマルチキャスト方式にすることにより、Hot-standby 構成のような主副関係の集権型監視クラスターを特別に用意しなくても、個々のコンピュータが相互に監視しあう分散型自律ネットワークが可能となりえます。
また、結果整合性データ群については、マルチキャストグループへの一斉同期により、RDB や KVS 等でよくあるマスター/スレーブのような煩雑な主副関係のクラスター構成を排除する事が要件によっては可能となりえます。
これらの設計手法については、集権型管理か分散型管理かなどの 0/1 の極論ではなく、目的に応じて手段を選択していくことによって、より生産性の高い設計が実現できるようになるでしょう。
UDP やマルチキャストはそれらの手段の一つであり、今後は更にこれらが選択される機会は増えていくでしょう。

IPv6 によるマルチキャストの実現方法については次回投稿しますが、今回の記事ではまず、IPv4 のマルチキャスト実現のための Golang のサンプルコードを投稿します。
(IPv6 によるマルチキャストのための Golang のサンプルコードを “IPv6 によるマルチキャスト” で投稿しました。)

3. 環境

  • RHEL-7 系
  • Go 1.9

4. 設計

  • IPv4 マルチキャスト送信サーバー x 1
    • sender1: 192.0.2.1
  • IPv4 マルチキャスト受信サーバー x 2
    • receiver1: 192.0.2.2
    • receiver2: 192.0.2.3

5. IPv4 マルチキャストアドレス

IPv4 アドレスでは、クラス D のアドレス範囲がマルチキャストアドレスとして予約されています。

224.0.0.0/4(224.0.0.0 ~ 239.255.255.255)

また、以下の範囲が、ローカルマルチキャストアドレス用として予約されていますので、テストなどにも使用可能です。

224.0.0.0/24(224.0.0.0 ~ 224.0.0.255)

この記事では、224.0.0.1 の IPv4 マルチキャストアドレスと 56789 ポートを例示に使用します。

6. Golang サンプルコード

@ sender1
$ sudo nvim ~/go/ipv4_multicast_sender.go

~/go/ipv4_multicast_sender.go
package main

import (
    "fmt"
    "net"
    "strconv"
    "time"
)

func main() {
    ipv4 := "224.0.0.1"
    port := ":56789"
    addr := ipv4 + 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/ipv4_multicast_receiver.go

~/go/ipv4_multicast_receiver.go
package main

import (
    "fmt"
    "net"
)

func main() {
    ipv4 := "224.0.0.1"
    port := ":56789"
    addr := ipv4 + 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/ipv4_multicast_receiver.go

@ sender1
$ sudo go run ~/go/ipv4_multicast_sender.go

8. まとめ

この記事では、IPv4 のマルチキャストの実現方法を Golang のサンプルコードで例示しました。
UDP マルチキャストは、要件によっては、効率的な死活監視や、自律ネットワーク、あるいは No Cluster データリソースなどの設計が可能となりえます。