IPv4 によるブロードキャスト


1. 概要

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

2. はじめに

前回までの記事では、IPv4 や IPv6 によるマルチキャストの記事を投稿しました。

今回の記事では、IPv4 によるブロードキャスト実現のための Golang サンプルコードにより、以下 2 パターンのアドレスを使用して動作の検証を行います。

  • ブロードキャストアドレス 1(192.0.2.255/24)
  • ネットワークアドレス2(192.0.2.0/24)

ブロードキャストは、マルチキャスト同様、UDP 通信となり、送信ノードの処理コスト削減にはとても有用ですが、特にブロードキャストの場合には、ネットワークコストや中継ノードのコスト増になるケースもありますので、適宜最適なキャストタイプの選択をした設計が必要でしょう。

3. 環境

  • RHEL-7 系
  • Go 1.9

4. 構成

  • node1
    • 192.0.2.1/24
  • node2
    • 192.0.2.2/24

5. Golang サンプルコード

@ node1, 2
$ sudo nvim ~/go/broadcast_ipv4.go

~/go/broadcast_ipv4.go
package main

import (
    "fmt"
    "net"
    "os"
    "time"
)

var InboundToAddr string = "" // 動作検証で切り替えます
var OutboundFromAddr string = "" // 動作検証で切り替えます
var OutboundToAddr string = "" // 動作検証で切り替えます
var BufferByte int = 64
var IntervalSeconds int = 1

func main() {

    // Start inbound
    go func() {
        inbound_to_addr_byte, err := net.ResolveUDPAddr("udp", InboundToAddr)
        Error(err)

        inbound, err := net.ListenUDP("udp", inbound_to_addr_byte)
        Error(err)
        defer inbound.Close()
        fmt.Printf("Listened *:* > %s\n", InboundToAddr)

        buffer := make([]byte, BufferByte)
        for {
            // Inbound message
            length, inbound_from_addr_byte, err := inbound.ReadFrom(buffer)
            Error(err)
            inbound_message := string(buffer[:length])

            inbound_from_addr := inbound_from_addr_byte.(*net.UDPAddr).String()

            fmt.Printf("Inbound %v > %v as “%s”\n", inbound_from_addr, InboundToAddr, inbound_message)
        }
    }()

    // Start outbound
    outbound_from_addr, err := net.ResolveUDPAddr("udp", OutboundFromAddr)
    outbound_to_addr, err := net.ResolveUDPAddr("udp", OutboundToAddr)
    outbound, err := net.DialUDP("udp", outbound_from_addr, outbound_to_addr)
    Error(err)
    defer outbound.Close()
    fmt.Printf("Connected %s > %s\n", OutboundFromAddr, OutboundToAddr)

    // Get hostname
    outbound_message, err := os.Hostname()
    Error(err)

    for {
        time.Sleep(time.Duration(IntervalSeconds) * time.Second)

        // Outbound message
        outbound.Write([]byte(outbound_message))
        fmt.Printf("Outbound %v > %v as “%s”\n", outbound_from_addr, outbound_to_addr, outbound_message)
    }

}

func Error(_err error) {
    if _err != nil {
        panic(_err)
    }
}

6. Golang サンプル実行

以下では、ブロードキャストアドレスへの送受信と、ネットワークアドレスへの送受信のパターンの動作検証をします。

6-1. ブロードキャストアドレス

ブロードキャストアドレスへの送受信の動作検証を実施します。

@ node1
送信: 192.0.2.1:56789 > 192.0.2.255:56789
受信: all > 192.0.2.255:56789
$ sudo nvim ~/go/broadcast_ipv4.go

~/go/broadcast_ipv4.go
var InboundToAddr string = "192.0.2.255:56789" // ブロードキャストアドレス
var OutboundFromAddr string = "192.0.2.1:56789"
var OutboundToAddr string = "192.0.2.255:56789" // ブロードキャストアドレス

@ node2
送信: 192.0.2.2:56789 > 192.0.2.255:56789
受信: all > 192.0.2.255:56789
$ sudo nvim ~/go/broadcast_ipv4.go

~/go/broadcast_ipv4.go
var InboundToAddr string = "192.0.2.255:56789" // ブロードキャストアドレス
var OutboundFromAddr string = "192.0.2.2:56789"
var OutboundToAddr string = "192.0.2.255:56789" // ブロードキャストアドレス

@ node1
受信成功

[user@node1 ~/go]$ sudo go run broadcast_ipv4.go
Connected 192.0.2.1:56789 > 192.0.2.255:56789
Listened *:* > 192.0.2.255:56789
Outbound 192.0.2.1:56789 > 192.0.2.255:56789 as “node1”
Inbound 192.0.2.1:56789 > 192.0.2.255:56789 as “node1”
Inbound 192.0.2.2:56789 > 192.0.2.255:56789 as “node2”
...

@ node2
受信成功

[user@node2 ~/go]$ sudo go run broadcast_ipv4.go
Connected 192.0.2.2:56789 > 192.0.2.255:56789
Listened *:* > 192.0.2.255:56789
Outbound 192.0.2.2:56789 > 192.0.2.255:56789 as “node2”
Inbound 192.0.2.1:56789 > 192.0.2.255:56789 as “node1”
Inbound 192.0.2.2:56789 > 192.0.2.255:56789 as “node2”
...

6-2. ネットワークアドレス

ネットワークアドレスへの送受信の動作検証を実施します。

@ node1
送信: 192.0.2.1:56789 > 192.0.2.0:56789
受信: all > 192.0.2.0:56789
$ sudo nvim ~/go/broadcast_ipv4.go

~/go/broadcast_ipv4.go
var InboundToAddr string = "192.0.2.0:56789" // ネットワークアドレス
var OutboundFromAddr string = "192.0.2.1:56789"
var OutboundToAddr string = "192.0.2.0:56789" // ネットワークアドレス

@ node2
送信: 192.0.2.2:56789 > 192.0.2.0:56789
受信: all > 192.0.2.0:56789
$ sudo nvim ~/go/broadcast_ipv4.go

~/go/broadcast_ipv4.go
var InboundToAddr string = "192.0.2.0:56789" // ネットワークアドレス
var OutboundFromAddr string = "192.0.2.2:56789"
var OutboundToAddr string = "192.0.2.0:56789" // ネットワークアドレス

@ node1
受信成功

[user@node1 ~/go]$ sudo go run broadcast_ipv4.go
Connected 192.0.2.1:56789 > 192.0.2.0:56789
Listened *:* > 192.0.2.0:56789
Outbound 192.0.2.1:56789 > 192.0.2.0:56789 as “node1”
Inbound 192.0.2.1:56789 > 192.0.2.0:56789 as “node1”
Inbound 192.0.2.2:56789 > 192.0.2.0:56789 as “node2”
...

@ node2
受信成功

[user@node2 ~/go]$ sudo go run broadcast_ipv4.go
Connected 192.0.2.2:56789 > 192.0.2.0:56789
Listened *:* > 192.0.2.255:56789
Outbound 192.0.2.2:56789 > 192.0.2.0:56789 as “node2”
Inbound 192.0.2.1:56789 > 192.0.2.0:56789 as “node1”
Inbound 192.0.2.2:56789 > 192.0.2.0:56789 as “node2”
...

7. まとめ

この記事では、IPv4 によるブロードキャスト実現のための Golang サンプルコード投稿しました。
このように、ブロードキャストアドレスやネットワークアドレスの利用により、サブネット内におけるブロードキャストが実現可能となります。
また、マルチキャストと同様、ブロードキャストも UDP 通信となり、送信ノードの処理コスト削減にはとても有用ですが、特にブロードキャストの場合には、ネットワークコストや中継ノードのコスト増になるケースもありますので、適宜最適なキャストタイプの選択をした設計が必要でしょう。