Open sgrekhov opened 2 years ago
I believe it is working as expected based on this documentation of the options in Linux socket API
SO_REUSEPORT (since Linux 3.9)
Permits multiple AF_INET or AF_INET6 sockets to be bound
to an identical socket address. This option must be set
on each socket (including the first socket) prior to
calling [bind(2)](https://man7.org/linux/man-pages/man2/bind.2.html) on the socket. To prevent port hijacking,
all of the processes binding to the same address must have
the same effective UID. This option can be employed with
both TCP and UDP sockets.
For TCP sockets, this option allows [accept(2)](https://man7.org/linux/man-pages/man2/accept.2.html) load
distribution in a multi-threaded server to be improved by
using a distinct listener socket for each thread. This
provides improved load distribution as compared to
traditional techniques such using a single [accept(2)](https://man7.org/linux/man-pages/man2/accept.2.html)ing
thread that distributes connections, or having multiple
threads that compete to [accept(2)](https://man7.org/linux/man-pages/man2/accept.2.html) from the same socket.
For UDP sockets, the use of this option can provide better
distribution of incoming datagrams to multiple processes
(or threads) as compared to the traditional technique of
having multiple processes compete to receive datagrams on
the same socket.
Per this when SO_REUSEPORT is set on both socket1 and socket2, bind should succeed.
SO_REUSEADDR
Indicates that the rules used in validating addresses
supplied in a [bind(2)](https://man7.org/linux/man-pages/man2/bind.2.html) call should allow reuse of local
addresses. For AF_INET sockets this means that a socket
may bind, except when there is an active listening socket
bound to the address. When the listening socket is bound
to INADDR_ANY with a specific port then it is not possible
to bind to this port for any local address. Argument is
an integer boolean flag.
Per this a socket not needing to call “listen” system call is allowed to bind to the exact same ip address and same port of another socket with same option (TCP Client, UDP Server , UDP Client)
If this is an expected, then please, add this info to the bind()
method documentation. Consider
final socket1 = await RawDatagramSocket.bind(localhost, 0, reusePort: false);
final socket2 = await RawDatagramSocket.bind(localhost, socket1.port, reusePort: false);
I'd expect the above produces a SocketException
because reusePort: false
but, in fact, there is no error here because both socket1
and socket2
have optional parameter reuseAddress
with the default value true
. It's not obvious to figure out why there is no exception here with the current documentation.
Also, if these parameters are not supported under Windows (see https://github.com/dart-lang/sdk/issues/49598) then add it to the documentation
Will update the docs, thanks.
@a-siva similar to HttpServer.bind() please also add
If port has the value 0 an ephemeral port will be chosen by the system. The actual port used can be retrieved using the port getter.
For Mac and dart legacy see https://github.com/dart-lang/sdk/issues/50172
Please see
RawDatagramSocket.bind()
documentationBut in fact, the actual the behaviour is quite sophisticated. Consider the following test
Now let's play with
socket1
andsocket2
parameters. Results are the followingAnalyzing the table above we came to conclusion that sockets may share the same address if they both have either
reuseAddress: true
eitherreusePort: true
. Is this expected? If so, then it should be clearly reflected in the documentation. Now it is not clear what is the difference between these two parametersAlso, having two parameters named
reusePort
andreuseAddress
is a bit of misleading because port is the part of the addressTested on the edge version of the SDK
Dart SDK version: 2.19.0-edge.5b489e6505de3dc6fde98c136862ac4a89724fea (be) (Fri Aug 5 08:10:01 2022 +0000) on "linux_x64"