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
andgprbuild
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:
- 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)
- 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 customreadObject
andwriteObject
methods. (Serialization of lists is already optimized ...)You don't need to subclass
LinkedList
to do this. It is alreadySerializable
.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 ofQueue
orDeque
.
Related Topics
Socket Send Concurrency Guarantees
Show Image Notification from Bash Script
Bash-Script Printing a PDF to a PDF in Linux
Why Can One Remove/Rename Open Files in Linux
Run Shell Script After Xserver Is Started
How to Get Pyinstaller to Working on Ubuntu
Pte Structure in The Linux Kernel
Incorrect Rendering in Anaconda + Spyder (Wrong Colours in Text)
Curl Http Post File Upload Using Curl -Data in Linux Command Line
How to Highlight The Differences Between Subsequent Lines in a File
How to Use/Learn Video4Linux2 (On Screen Display) Output APIs
How to Add a Custom System Call on X86 Ubuntu Linux
How to Connect to Sftp Using Linux Command from Perl
How to Install Packages in Tcl