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) | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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).