Skip to content

Instantly share code, notes, and snippets.

@joliver
Last active September 27, 2023 22:30
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save joliver/4ccd58605e07e8edf71904b172d95513 to your computer and use it in GitHub Desktop.
Save joliver/4ccd58605e07e8edf71904b172d95513 to your computer and use it in GitHub Desktop.
Go v1.11 net.Listener SO_REUSEPORT or SO_REUSEADDR example
package main
// This is a super-quick example of how to set the socket options to allow port re-use for a single address/port on a host machine.
// This is most commonly used with things like hot reloads of configuration.
import (
"context"
"log"
"net"
"syscall"
)
func main() {
const network = "tcp"
const address = "127.0.0.1:8080"
config := &net.ListenConfig{Control: reusePort}
listener1, _ := config.Listen(context.Background(), network, address) // bind to the address:port
go listen(1, listener1)
// as soon as listener2 is bound below, all traffic will begin to flow it instead of listener1. the only thing left to do
// with listener1 is to shut down any active connections and close the listener.
listener2, _ := config.Listen(context.Background(), network, address) // also bind to the address:port
listen(2, listener2)
}
func listen(id int, listener net.Listener) {
socket, _ := listener.Accept()
log.Println("Accepted socket from listener", id)
socket.Close()
listener.Close()
}
func reusePort(network, address string, conn syscall.RawConn) error {
return conn.Control(func(descriptor uintptr) {
syscall.SetsockoptInt(int(descriptor), syscall.SOL_SOCKET, syscall.SO_REUSEPORT, 1)
})
}
@l0k18
Copy link

l0k18 commented Feb 22, 2020

This code let me get a multicast transport working, big thanks :) I had to use net.PacketConn however I'm not sure if that was relevant. It was required because I needed a net.Conn of some sort with destination pre-dialed for UDP, not a net.Listener. My code is here: p9c/pod-archive@cd85b2d

IMO the use of a multicast address for a listener should automatically set this configuration option. I posted my solution on an issue for the golang.org/x/net/ipv4 related to using multicast here: zeromq/libzmq#3236

@mholt
Copy link

mholt commented Apr 14, 2022

FYI, I had to find the SO_REUSEPORT identifier in the golang.org/x/sys/unix package (syscall is frozen and my Go distro doesn't have it in there).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment