Playing with the `net' module I found out that with UDP sockets
SO_REUSEADDR is set. I'm writing a program that must detect if certain
port is used by another process, therefore I disable SO_REUSEADDR in my
sockets to make them fail when it is the case so I can decide to open a
different port.
Looking into src/pkg/net/sock.go (func socket) I see that SO_REUSEADDR
is set unconditionally to all types of sockets.
AFAIK SO_REUSEADDR makes sense with TCP which it allows to reuse a
recently used port but the bind fails when other sockets is listening.
With UDP sockets it is not so clear to me if SO_REUSEADDR has any
advantage because it allows you to have two different process with the
same UDP port open, which could not what you want.
The important part of the issue is that timeouts with Read(), Write()
and their variants don't occur. When I disable SO_REUSEADDR the
Read()/Write() calls block forever even I previously used SetTimeout().
Am I doing something wrong? Is this supposed to happen?
At the end there is a small program to test this issue. Comment the line
that calls `setNoReuseAddress()' to let happen the timeout.
Thanks in advance.
package main
import (
"fmt"
"net"
"syscall"
)
func setNoReuseAddress(conn net.PacketConn) {
file, _ := conn.(*net.UDPConn).File()
fd := file.Fd()
syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 0);
}
func main() {
buff := make([]byte, 1024)
conn, _ := net.ListenPacket("udp", "localhost:10000")
setNoReuseAddress(conn)
conn.SetTimeout(500 * 1000 * 1000)
_, _, err := conn.ReadFrom(buff)
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
fmt.Println("Timeout reached")
}
}
--
Ricardo
I don't have any good answers for you. I'd be willing to drop SO_REUSEADDR
but I have no idea why that would affect the timeouts.
Russ