Listing Multicast Sockets

Receiving multicast traffic using GNAT.Sockets

Based on the example in GNAT.Sockets, the code below should work. I've removed some options as they are not relevant for receiving.

receive_multicast.ads

procedure Receive_Multicast 
(IP_Address : String;
Port : String);

receive_multicast.adb

with Ada.Text_IO;
with Ada.Streams;
with GNAT.Sockets;

procedure Receive_Multicast
(IP_Address : String;
Port : String)
is

use GNAT.Sockets;

Address : Sock_Addr_Type;
Socket : Socket_Type;

begin

Create_Socket (Socket, Family_Inet, Socket_Datagram);

Set_Socket_Option
(Socket => Socket,
Level => Socket_Level,
Option => (Reuse_Address, True));

Address.Addr := Any_Inet_Addr;
Address.Port := Port_Type'Value (Port);

Bind_Socket (Socket, Address);

-- Join a multicast group

-- Portability note: On Windows, this option may be set only
-- on a bound socket.

Set_Socket_Option
(Socket => Socket,
Level => IP_Protocol_For_IP_Level,
Option => (Add_Membership, Inet_Addr (IP_Address), Any_Inet_Addr));

-- Receive the packet from the socket.
declare

use Ada.Text_IO;
use Ada.Streams;

Data : Stream_Element_Array (1 .. 2**16);
Offset : Stream_Element_Offset;
Sender : Sock_Addr_Type;

begin
Put_Line ("Waiting for incoming packets...");

Receive_Socket
(Socket => Socket,
Item => Data,
Last => Offset,
From => Sender);

Put_Line ("Received " & Offset'Image & " bytes.");
end;

end Receive_Multicast;

main.adb

with Receive_Multicast;

procedure Main is
begin
Receive_Multicast
(IP_Address => "239.255.128.128",
Port => "8807");
end Main;

I couldn't test the code extensively, but when I open Windows PowerShell ISE, load and run the script Send-UdpDatagram.ps1 (see this GitHub Gist) and then execute:

PS C:\> Send-UdpDatagram -EndPoint "239.255.128.128" -Port 8807 -Message "testing"

Then the Ada program responds with:

Waiting for incoming packets...
Received 7 bytes.
[2019-09-29 10:55:58] process terminated successfully, elapsed time: 07.60s

Update

I also tested the example code with a Raspberry Pi running Raspbian GNU/Linux 10 (buster):

  • Installed APT packages gnat and gprbuild on the Raspberry Pi.
  • Copied the code to the Raspberry Pi.
  • Compiled it with GNAT FSF (gprbuild -p <proj_name>.gpr).
  • Started four instances of the program, each in a separate terminal.
  • Emitted a packet from a Windows 10 host using the PowerShell function as before.

The result was the same: the packet was received by all four program instances on the Raspberry Pi. While the programs were waiting for the packet, I could see the memberships (see also this post on SO):

pi@raspberrypi:~ $ netstat -g
IPv6/IPv4 Group Memberships
Interface RefCnt Group
--------------- ------ ---------------------
[...]
eth0 4 239.255.128.128
[...]
pi@raspberrypi:~ $ netstat -anu | sort -nk4
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
[...]
udp 0 0 0.0.0.0:8807 0.0.0.0:*
udp 0 0 0.0.0.0:8807 0.0.0.0:*
udp 0 0 0.0.0.0:8807 0.0.0.0:*
udp 0 0 0.0.0.0:8807 0.0.0.0:*
[...]

List of all hosts subscribing to a multicast group

No, there is no central authority of group membership. You have two choices:

  1. Set up a master/slave protocol that allows the peers to elect a master to which new peers can send group membership queries (a la NetBIOS)
  2. Have each peer send its own membership announcement message periodically so new members can eventually accumulate a list of peers.

keep clients notified of List via datagram/multicast

Multi-casting the updated list each time it changes is certainly simple, but there may be issues.

  • If the list gets large or the updates are frequent, scalability may be a concern. Consider sending the changes to the list as "deltas" rather than sending the entire list each time.

  • Serialization using ObjectOutputStream can be expensive, though you can improve the performance by writing custom readObject and writeObject methods. (Serialization of lists is already optimized ...)

  • You don't need to subclass LinkedList to do this. It is already Serializable.

  • You most likely need to synchronize the list structure to avoid race conditions and mayhem, but that will create a potential bottleneck. Consider replacing the List with a concurrent implementation of Queue or Deque.



Related Topics



Leave a reply



Submit