SO_REUSEADDR in UDP sockets

901 views
Skip to first unread message

Ricardo Catalinas Jiménez

unread,
Apr 12, 2011, 5:14:11 PM4/12/11
to golan...@googlegroups.com
Hi,

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

Russ Cox

unread,
Apr 22, 2011, 4:15:47 PM4/22/11
to golan...@googlegroups.com
> 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?

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

Reply all
Reply to author
Forward
0 new messages