How to set socket option for a "TCPListener" before bind?

1,161 views
Skip to first unread message

Ewan Chou

unread,
Jun 24, 2013, 7:35:23 PM6/24/13
to golan...@googlegroups.com
I can get the "syscall.Handle" from a "TCPListener" by reflection, and call "syscall.SetsockoptInt".

But the type of the only field of "TCPListener" is "netFD" which is unexported, so the only way to get a "TCPListener" is to call "net.ListenTCP".

But the listener is already bound.

My need is to set "SO_EXCLUSIVEADDRUSE" option for a TCP listener on WINDOWS, so more than one processes can listen to the same port.

that option can be set only before bind.

How can I do that?

Ewan Chou

unread,
Jun 24, 2013, 8:38:35 PM6/24/13
to golan...@googlegroups.com
I tried to call “syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, ^syscall.SO_REUSEADDR)” directly, but I got the error "not supported by windows".

Dave Cheney

unread,
Jun 24, 2013, 8:47:39 PM6/24/13
to Ewan Chou, golang-nuts
If you're really keen on doing this you'll find a hint in the
go.net/ipv4. From my reading SO_EXCLUSIVEADDRUSE does exactly the
opposite of what you want.
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Ewan Chou

unread,
Jun 24, 2013, 9:02:38 PM6/24/13
to golan...@googlegroups.com, Ewan Chou
I thought SO_EXCLUSIVEADDRUSE is set to 1 by default, I wanted to set it to 0.

What does "go.net/ipv4" mean? I can't find the package.

Dave Cheney

unread,
Jun 24, 2013, 9:05:19 PM6/24/13
to Ewan Chou, golan...@googlegroups.com, Ewan Chou

Ewan Chou

unread,
Jun 24, 2013, 10:35:15 PM6/24/13
to golan...@googlegroups.com, Ewan Chou
Thanks, now I can get and set socket options on windows.

I found out that when I get the listener by calling "net.Listen", the default value of SO_EXCLUSIVEADDRUSE is 0, so no need to set it.

But the default value of SO_REUSEADDR is also 0, unlike on Linux which is set to 1.

I can make two processes listen on the same port now, but only through "syscall".

Still can't find a way to set the socket option before bind with "net" package.

Dave Cheney

unread,
Jun 24, 2013, 10:38:40 PM6/24/13
to Ewan Chou, golang-nuts
> I can make two processes listen on the same port now, but only through
> "syscall".

Why do you need to do such a thing ? The only use cases for this
facility that I am aware of is listening to a UDP port for multicast
messages (ie, mDNS)

Ewan Chou

unread,
Jun 24, 2013, 10:46:33 PM6/24/13
to golan...@googlegroups.com, Ewan Chou
If two process can listen on the same port, then the application can do zero-downtime restart.

Dave Cheney

unread,
Jun 24, 2013, 10:50:52 PM6/24/13
to Ewan Chou, golang-nuts
Ok, so now we're getting to the actual problem you are trying to solve.

Some comments

1. Do you really need zero downtime, how about 1 second downtime ? 5
seconds, 10 seconds ?
2. If you really need zero downtime, then you can't achieve that with
a single process, so you're really talking about how to cleanly
shutdown one worker at a time for a rolling upgrade scenario.
3. You should research how products like nginx do process restarts,
they don't use socket tricks like this, they just pass the accepting
socket down to a child process.

So, some questions

1. what platform(s) are you targeting ?
2. what is your SLA ?
3. how are you currently managing your process at the moment, and how
quickly can it restart the process if it fails ?

Cheers

Dave

Ewan Chou

unread,
Jun 24, 2013, 11:15:08 PM6/24/13
to golan...@googlegroups.com, Ewan Chou
I'm not targeting on windows, but I'm used to write code on windows, I want my application to be able to run on windows as well as on linux.

There is no issue on my targeting platform(Linux).

If it is impossible, I can live with it.

But I still think the "net" package should give user a chance to set socket option before bind.

Thanks for your help.

Rémy Oudompheng

unread,
Jun 25, 2013, 3:08:27 AM6/25/13
to Ewan Chou, golan...@googlegroups.com
It is not possible on linux (versions before 3.9) to have two sockets
listening on the same address, you need to share sockets between the
processes in order to do that, and this is different from setsockopt.
On very recent kernels the SO-REUSEPORT option made this possible.


Rémy.


2013/6/25, Ewan Chou <coo...@gmail.com>:
>> <coo...@gmail.com<javascript:>>
>> wrote:
>> > If two process can listen on the same port, then the application can do
>> >
>> > zero-downtime restart.
>> >
>> > On Tuesday, June 25, 2013 10:38:40 AM UTC+8, Dave Cheney wrote:
>> >>
>> >> > I can make two processes listen on the same port now, but only
>> through
>> >> > "syscall".
>> >>
>> >> Why do you need to do such a thing ? The only use cases for this
>> >> facility that I am aware of is listening to a UDP port for multicast
>> >> messages (ie, mDNS)
>> >
>> > --
>> > You received this message because you are subscribed to the Google
>> Groups
>> > "golang-nuts" group.
>> > To unsubscribe from this group and stop receiving emails from it, send
>> an
>> > email to golang-nuts...@googlegroups.com <javascript:>.
Reply all
Reply to author
Forward
0 new messages