使用GNAT.Sockets接收IP组播流量失败的问题排查与解决
Ada组播接收阻塞问题排查与解决
我最近在做Ada语言的IP组播实验时碰到了个棘手的问题:监听程序完全收不到发往目标组播组的流量,调用Receive_Socket后一直阻塞,但实际组播数据包是存在的。
已完成的排查验证:
- 用Wireshark抓包确认:本机已发送组播加入请求,且确实有数据发往目标组播组
239.255.128.128:8807 - 用Windows命令
netsh interfaces ip show joins验证:程序运行时目标组播组的引用计数为1,关闭程序后计数回到0,说明操作系统已正确注册组播成员关系
我的监听程序代码(调用参数:Mcast_IP => "239.255.128.128"、Mcast_Port => "8807"):
with GNAT.Sockets; with Ada.Streams; with Ada.Text_IO; procedure Receive_Multicast (Mcast_IP : in String; Mcast_Port : in String) is package GS renames GNAT.Sockets; package AS renames Ada.Streams; package Tio renames Ada.Text_IO; 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调用处持续阻塞,明明Wireshark能看到组播包抵达本机,但程序就是接收不到。
最终解决办法:
折腾半天发现是卡巴斯基杀毒软件拦截了本机的组播回环流量,卸载卡巴斯基之后,程序立刻就能正常接收组播数据包了!另外要说明的是,这段代码本身是完全合规的,公认的组播监听实现方案也能完美适配这个场景。
内容的提问来源于stack exchange,提问作者chrillof
相关产品推荐
相关产品推荐

