Re-using sockets on Windows

My program stops a net.Listener and then creates a new one immediately on the same port. On Linux this works fine, presumably due to SO_REUSEADDR being 1 by default, but on Windows, I get:

bind: Only one usage of each socket address (protocol/network address/port) is normally permitted.

So I tried this sycall before binding:

f, err := ln.File()
if err != nil {
    return err
}
syscall.SetSockoptInt(syscall.Handle(f.Fd()), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)

I still get the error though. (Actually, it seems racy. If I time.Sleep(100 * time.Millisecond) between stopping the listener and starting the new one, the error is almost always absent.)

What’s the proper way to be able to reuse a port immediately after closing it? Or, what’s a good way to forcibly close the socket on Windows?

Dang - turns out my calling function was ignoring the error (oops… you’d think I’d learn by now, even in spike code).

The error returned when calling File() is:

not supported by Windows

(ln is a type *net.TCPListener.)

So I can see that dup() is not implemented in Windows (scroll to bottom) but surely there’s a way to get a syscall.Handle to the socket somehow?

Edit: I found this about UDPConn, but I figure the same discouraging thing could be said of TCPListener: sockets - Get syscall.Handle from a Go *net.UDPConn on Windows? - Stack Overflow. Since I’m not interested in going the unsafe route (or any cgo route) perhaps I should abandon hope and just time.Sleep between restarts…

I’d recommend doing time.Sleep until the reconnect is successful, with a timeout of a few seconds total.

1 Like

That is what I’m doing for now. Windows users are just going to have to find another way if they want true zero-downtime. ¯\_(ツ)_/¯

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.