Golang UDP server and client: ListenPacket, DialUDP, and sending packets

Tech reviewed: Deepak Prasad
Golang UDP server and client: ListenPacket, DialUDP, and sending packets

This tutorial covers a golang udp server and golang udp client with the standard net package: ListenPacket for a udp server golang style listener, ReadFrom and WriteTo on the server, and ResolveUDPAddr with DialUDP plus Write for golang send udp packet flows. Together they form a minimal go udp server and client pair you can extend. If you also want a reliable stream, compare with Golang TCP server and client.

Examples assume a recent Go toolchain on Linux. Run the server and client in two terminals on the same machine; both programs bind or dial a local UDP port (1053 in the samples).


UDP, TCP, and the Go net package

UDP is connectionless: each datagram is independent, there is no built-in retry, and ordering is not guaranteed. That suits latency-sensitive workloads where applications tolerate loss. TCP is connection-oriented and reliable—better when you need an ordered byte stream.

The net package documents Dial, Listen, ListenPacket, and types such as PacketConn and UDPConn. For UDP, ListenPacket("udp", address) returns a PacketConn suitable for ReadFrom and WriteTo. A UDPConn from DialUDP supports Read and Write to one peer.


Golang udp server example: ListenPacket, ReadFrom, WriteTo

ListenPacket announces on a local UDP address. Use udp, udp4, or udp6 as needed. The server loop allocates a buffer, calls ReadFrom, and must use only the n bytes returned (buf[:n]) when building a reply so you do not echo uninitialized buffer tail (a common bug in udp server example code).

Avoid shadowing the time package with a local variable named time; use something like ts for the formatted timestamp.

go
package main

import (
	"fmt"
	"log"
	"net"
	"time"
)

func main() {
	pc, err := net.ListenPacket("udp", ":1053")
	if err != nil {
		log.Fatal(err)
	}
	defer pc.Close()

	for {
		buf := make([]byte, 1024)
		n, addr, err := pc.ReadFrom(buf)
		if err != nil {
			log.Println("read:", err)
			continue
		}
		go respond(pc, addr, buf[:n])
	}
}

func respond(pc net.PacketConn, addr net.Addr, payload []byte) {
	ts := time.Now().Format(time.ANSIC)
	msg := fmt.Sprintf("time received: %s. Your message: %s!", ts, string(payload))
	if _, err := pc.WriteTo([]byte(msg), addr); err != nil {
		log.Println("write:", err)
	}
}

Start this program in one terminal; it listens on UDP port 1053 on all interfaces.


Golang udp client, go udp, and golang send udp packet

The client resolves 127.0.0.1:1053 (adjust if your server binds elsewhere), opens a UDPConn with DialUDP, then Write sends the datagram—this is the usual golang send udp packet path from a client. Read waits for one reply (set deadlines in real services so Read cannot hang forever).

go
package main

import (
	"fmt"
	"log"
	"net"
)

func main() {
	raddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:1053")
	if err != nil {
		log.Fatal(err)
	}
	c, err := net.DialUDP("udp", nil, raddr)
	if err != nil {
		log.Fatal(err)
	}
	defer c.Close()

	if _, err := c.Write([]byte("This is a UDP message")); err != nil {
		log.Fatal(err)
	}

	buf := make([]byte, 2048)
	n, err := c.Read(buf)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(string(buf[:n]))
}

With the server running, this client prints one line containing your payload and a timestamp—similar to the historical sample output for this go udp walkthrough.


Run this udp example locally

  1. Save the server as server.go, the client as client.go (or use one module with two main packages in subfolders).
  2. Run go run server.go first.
  3. In another shell, run go run client.go.

If bind: address already in use appears, pick another free port in both programs. For production code, add SetReadDeadline and SetWriteDeadline, structured logging, and consider message size limits (very large UDP payloads may fragment).


Summary

Golang udp networking centers on net.ListenPacket for a golang udp server example that reads datagrams with ReadFrom and replies with WriteTo per net.Addr, and on ResolveUDPAddr plus DialUDP for a golang udp client where golang send udp packet work uses Write. Go udp server and udp server golang searches map to the same pattern: bound PacketConn, correct buf[:n] slicing, and goroutines only if you accept concurrent handlers—see goroutines in Go for background on the go statement here. Udp example readers should treat UDP as datagram-based, unlike TCP sessions in the TCP article, and validate buffer sizes and timeouts for their workload.


References


Frequently Asked Questions

1. What is the difference between TCP and UDP in Go?

TCP gives reliable ordered streams via net.Dial and net.Listen; UDP sends independent datagrams with net.ListenPacket and net.DialUDP, which is faster but delivery is not guaranteed.

2. How do I create a golang udp server?

Call net.ListenPacket with network udp and an address like :1053, loop ReadFrom into a buffer, then WriteTo responses using the net.Addr from ReadFrom.

3. How do I send a UDP packet from a Go client?

Resolve the server UDP address, open a connection with DialUDP, then conn.Write payload bytes; read the reply with conn.Read into a buffer.

4. Why should ReadFrom use the returned length n?

Only buf[:n] contains the datagram; passing the full buffer to string or echo can include zero bytes past the message.

5. Can I use net.Dial instead of DialUDP?

Yes, net.Dial with udp returns a net.Conn that supports Read and Write for connected-mode UDP to one peer.
Tuan Nguyen

Data Scientist

Proficient in Golang, Python, Java, MongoDB, Selenium, Spring Boot, Kubernetes, Scrapy, API development, Docker, Data Scraping, PrimeFaces, Linux, Data Structures, and Data Mining. With expertise spanning these technologies, he develops …

  • Deep Learning with TensorFlow
  • Machine Learning with Python
  • Go (programming language)
  • Python (programming language)
  • Java (programming language)
  • MongoDB