Last active
September 27, 2023 22:30
-
-
Save joliver/4ccd58605e07e8edf71904b172d95513 to your computer and use it in GitHub Desktop.
Go v1.11 net.Listener SO_REUSEPORT or SO_REUSEADDR example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
}) | |
} |
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
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 anet.Conn
of some sort with destination pre-dialed for UDP, not a net.Listener. My code is here: p9c/pod-archive@cd85b2dIMO 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