Получение многоадресного трафика с использованием GNAT.Sockets - PullRequest
1 голос
/ 29 сентября 2019

Я экспериментирую с многоадресной рассылкой IP-адресов в Ada, но, похоже, не получаю трафик, отправленный в группу многоадресной рассылки.Почему-то кажется, что я не могу заставить приложение извлекать входящие пакеты.

Я могу проверить (используя Wireshark), что многоадресное соединение отправлено с моего компьютера, а также я могу убедиться, что данные отправляютсяв группу многоадресной рассылки.

Я могу убедиться, что в ОС зарегистрировано многоадресное соединение, зарегистрированное с помощью команды netsh:

netsh interfaces ip show joins

Моя группа отображается со ссылкой 1, если я запускаю свою программу и0, если это не так.

Следующая процедура показывает моего слушателя, и я вызываю его, используя Mcast_IP => "239.255.128.128" и Mcast_Port => "8807":

   procedure Receive_Multicast (Mcast_IP   : in String;
                                Mcast_Port : in String)
   is
      use GS;

      use type Ada.Streams.Stream_Element_Offset;
      Socket  : GS.Socket_Type;
      Address : GS.Sock_Addr_Type;
      Data    : AS.Stream_Element_Array (1 .. 2**16);
      Offset  : AS.Stream_Element_Offset;
      Sender  : GS.Sock_Addr_Type;
   begin
      Address.Addr := Any_Inet_Addr;
      Address.Port := Port_Type'Value (Mcast_Port);

      Create_Socket (Socket => Socket,
                     Family => Family_Inet,
                     Mode   => Socket_Datagram);

      Bind_Socket (Socket, Address);

      --  Set socket options
      Set_Socket_Option (Socket,
                         Socket_Level,
                         (Reuse_Address, True));

      Set_Socket_Option
        (Socket,
         IP_Protocol_For_IP_Level,
         (Multicast_TTL, 1));

      Set_Socket_Option
        (Socket,
        IP_Protocol_For_IP_Level,
        (Multicast_Loop, True));

      Set_Socket_Option
        (Socket,
         IP_Protocol_For_IP_Level,
         (Add_Membership, Inet_Addr (Mcast_IP), Any_Inet_Addr));

      Tio.Put_Line ("Listening for MULTICASTS on port " & Address.Port'Img);

--  Receive the packet from the socket.
      loop
         Tio.Put_Line ("Waiting for incoming packets...");
         Receive_Socket (Socket => Socket,
                         Item   => Data,
                         Last   => Offset,
                         From   => Sender);
         Tio.Put_Line ("Received " & Offset'Img & " bytes.");
      end loop;
   end Receive_Multicast;

Процедура продолжается вплоть до Receive_Socket вызов (это процедура в пакете GNAT.Sockets).Однако даже если я могу подтвердить многоадресный трафик с помощью Wireshark, вызов Receive_Socket продолжает блокироваться.

1 Ответ

4 голосов
/ 29 сентября 2019

На основании примера в GNAT.Sockets должен работать приведенный ниже код.Я удалил некоторые параметры, поскольку они не имеют отношения к получению.

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;

Я не смог подробно протестировать код, но когда я открываю Windows PowerShell ISE, загружаю и запускаю скрипт Send-UdpDatagram.ps1 (посмотрите этот GitHub Gist ) и затем выполните:

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

Затем программа Ada отвечает:

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