0

The question is tagged with Ada, since I need to code it in Ada. However, the problem is language independent.

I am in a situation where I have this network configuration. This is a given constraint, it cannot be changed for now.

  • 192.168.0.2
    • Emits UDP with broadcast : 224.224.0.1
    • on ports A and B
  • 192.168.0.3
    • Emits UDP with broadcast : 224.224.0.2
    • on ports A and B

I need to write a piece of software running on 192.168.0.1 that is able to receive data from one or the other.

What I tried so far :

  • Create 2 sockets bound to 192.68.0.2 + ports. Same if I want the other 2 sockets for 192.68.0.3).

This does not work. I get socket error 10049 can't assign address (see https://msdn.microsoft.com/en-us/library/windows/desktop/ms740668%28v=vs.85%29.aspx)

I've read this : What does it mean to bind a multicast (UDP) socket?. So I tried to switch to "Any".

  • Create 2 sockets bound to Any + relevant port (A and B)

This works, I can listen to anyone, but I can't tell who's talking to me. For small tests, it works. But I'll get into trouble when I'll have the second emitter involved.

-- emitter uses multicast
GNAT.Sockets.Set_Socket_Option (Socket => socket_data.Socket,
                              Level  => GNAT.Sockets.IP_Protocol_For_IP_Level,
                              Option => (Name              => GNAT.Sockets.Add_Membership,
                                         Multicast_Address => GNAT.Sockets.Inet_Addr (SERVER_MULTICAST_EMISSION_IP),
                                         Local_Interface   => GNAT.Sockets.Any_Inet_Addr));
Print ("Configure Receive socket - IP_Protocol_For_IP_Level Multicast_Address OK");

GNAT.Sockets.Set_Socket_Option (socket_data.Socket,
                              GNAT.Sockets.IP_Protocol_For_IP_Level,
                              (GNAT.Sockets.Multicast_Loop, True));
Print ("Configure Receive socket - IP_Protocol_For_IP_Level Multicast_Loop OK");

GNAT.Sockets.Set_Socket_Option (Socket => socket_data.Socket,
                              Option => (Name    => GNAT.Sockets.Receive_Timeout,
                                         Timeout => GNAT.Sockets.Timeval_Duration (0.03)));
Print ("Configure Receive socket - timeout OK");

-- bind to address+port
GNAT.Sockets.Bind_Socket (Socket  => socket_data.Socket,
                        Address => socket_data.Bound_To_Address);

My question is simple :

  • I feel that there is something wrong in my issue : having 2 emitters in broadcast on same ports make the filtering from the reception side a bit... tricky

  • On my machine 192.168.0.1, why can't I create the socket 192.168.0.2:A/192.168.0.2:B and bind to it ?

  • If I'm stuck with the "any" solution, how can I configure/program my sockets to filter out the emitter IP ?

(As mentioned aboved, I have already read the reference answers on sockets What does it mean to bind a multicast (UDP) socket? and Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems?)

Community
  • 1
  • 1
LoneWanderer
  • 3,058
  • 1
  • 23
  • 41

1 Answers1

1

Create 2 sockets bound to 192.68.0.2 + ports. Same if I want the other 2 sockets for 192.68.0.3).

Close, but no cigar. You need to not bind but connect the socket to the desired source address.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Forgot to mention I use the connect() feature in addition of bind(). I'll check my code to be sure. – LoneWanderer Apr 10 '17 at 10:49
  • So get rid of the failing bind. You can only bind to a local address. – user207421 Apr 10 '17 at 11:07
  • okay, my bad: I think was doing things fine at first (connect() instead of bind()). i'll update my question with the related code for consistency – LoneWanderer Apr 10 '17 at 12:05
  • I'll update my question with the related code for consistency. It appears I was using the bind() ... I'll give a try and vote your answer once I confirm it works :) (which I have no doubt it will work). – LoneWanderer Apr 10 '17 at 12:11