1
votes

I have two UDP sockets bound to the same address and connected to addresses A and B. I have two more UDP sockets bound to A and B and not connected.

This is what my /proc/net/udp looks like (trimmed for readability):

  sl  local_address rem_address
 3937: 0100007F:DD9C 0300007F:9910
 3937: 0100007F:DD9C 0200007F:907D
16962: 0200007F:907D 00000000:0000
19157: 0300007F:9910 00000000:0000

According to connect(2): "If the socket sockfd is of type SOCK_DGRAM, then addr is the address to which datagrams are sent by default, and the only address from which datagrams are received."

For some reason, my connected sockets are receiving packets that were destined for each other. eg: The UDP socket connected to A sends a message to A, A then sends a reply back. The UDP socket connected to B sends a message to B, B then sends a reply back. But the reply from A arrives at the socket connected to B and the reply from B arrives at the socket connected to A.

Why on earth would this be happening? Note that it happens randomly - sometimes the replies arrive at the correct sockets and sometimes they don't. Is there any way to prevent this or any situation under which connect is supposed to not work?

1
Here's a python example to reproduce this behavior: gist.github.com/povilasb/53f1c802dbc2aca36a0ffa5b4cb95536PovilasB

1 Answers

0
votes

Ehm, as far as I can see there is no ordering guarantee.

From the man page:

      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) 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) 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)ing thread that distributes connections, or having multiple threads that compete to accept(2) 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.

So you're using something that is mainly seen as a option for servers (or in some cases clients, but ordering can never be guaranteed - especially in UDP) as a client.

I suspect your approach is wrong, and needs a rethink =)

PS. Just had a quick glance but IMHO it's a bug in your approach