aler9 / howto-udp-broadcast-golang

Sample code and instructions on how to send and receive UDP broadcast packets in the Go programming language.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Howto: UDP broadcast in Go

Sample code and instructions on how to send and receive UDP broadcast packets in the Go programming language.

Introduction

A common method to trasmit informations to multiple devices connected to the same network consists in using the UDP transport layer and sending the packets to the network broadcast address. The router will take care of propagating the packets to each connected device. There are at least two advantages with respect to normal network communication:

  • transmission is much more efficient, as a single stream of data is used for communicating with multiple devices
  • it is not necessary to know in advance the addresses of the recipients

The Go programming languages offers at least 4 ways to send UDP broadcast packets, the situation is not very clear and that's the reason why this guide is being written.

Sending

Let's assume we want to transmit the ascii-encoded phrase "data to transmit" though port 8829 in a network with IP 192.168.7.2 and broadcast address 192.168.7.255.

The first (and preferred) method consists in using the net.ListenPacket() function:

package main

import (
  "net"
  "fmt"
)

func main() {
  pc, err := net.ListenPacket("udp4", ":8829")
  if err != nil {
    panic(err)
  }
  defer pc.Close()

  addr,err := net.ResolveUDPAddr("udp4", "192.168.7.255:8829")
  if err != nil {
    panic(err)
  }

  _,err := pc.WriteTo([]byte("data to transmit"), addr)
  if err != nil {
    panic(err)
  }
}

A second method consists in using the net.ListenUDP() function:

package main

import (
  "net"
)

func main() {
  listenAddr,err := net.ResolveUDPAddr("udp4", ":8829")
  if err != nil {
    panic(err)
  }
  list, err := net.ListenUDP("udp4", listenAddr)
  if err != nil {
    panic(err)
  }
  defer list.Close()

  addr,err := net.ResolveUDPAddr("udp4", "192.168.7.255:8829")
  if err != nil {
    panic(err)
  }

  _,err := list.WriteTo([]byte("data to transmit"), addr)
  if err != nil {
    panic(err)
  }
}

A third method consists in using the net.DialUDP() function:

package main

import (
  "net"
)

func main() {
  local,err := net.ResolveUDPAddr("udp4", ":8829")
  if err != nil {
    panic(err)
  }
  remote,err := net.ResolveUDPAddr("udp4", "192.168.7.255:8829")
  if err != nil {
    panic(err)
  }
  list, err := net.DialUDP("udp4", local, remote)
  if err != nil {
    panic(err)
  }
  defer list.Close()

  _,err := list.Write([]byte("data to transmit"))
  if err != nil {
    panic(err)
  }
}

A fourth and shorter way consists in using the net.Dial() function if the local address / port don't matter:

package main

import "net"

func main() {
  conn, err := net.Dial("udp", "192.168.7.255:8829")
  if err != nil {
    panic(err)
  }
  defer conn.Close()
  
  _, err := conn.Write([]byte("data to transmit"))
  if err != nil {
    panic(err)
  }

All four methods work and their result is indistinguishable. By looking at the Go source code, it is possible to assert that:

  • net.ListenPacket() and net.ListenUDP() use a nearly identical identical procedure, as they both call the same system functions, the only difference is that net.ListenPacket() converts the desired listen address (:8829) into an UDPAddr structure, while net.ListenUDP() requires directly an UDPAddr structure;
  • net.DialUDP() uses a different route and also provides a Write() function to write directly to the broadcast address. This could be confusing, as Go always work with WriteTo() and ReadFrom() when dealing with UDP connections.

Conclusion: I use with the ListenPacket() solution as it is the simpler one.

Receiving

Data can be received with a standard UDP server listening on the provided port:

package main

import (
  "fmt"
  "net"
)

func main() {
  pc,err := net.ListenPacket("udp4", ":8829")
  if err != nil {
    panic(err)
  }
  defer pc.Close()

  buf := make([]byte, 1024)
  n,addr,err := pc.ReadFrom(buf)
  if err != nil {
    panic(err)
  }
  
  fmt.Printf("%s sent this: %s\n", addr, buf[:n])
}

About

Sample code and instructions on how to send and receive UDP broadcast packets in the Go programming language.

License:The Unlicense