FCL应用技巧之------实现UDP组播

来源:互联网 发布:thinkphp js跳转页面 编辑:程序博客网 时间:2024/06/07 02:53

1 组播原理

组播的概念是在IP层定义的,一些特殊的IP地址被规定为组播IP地址,不能配置为某个主机的IP。具体说来,组播使用的IP地址是整个D类地址,即:



整个D类地址是不能配置到主机网卡上的,它们专门供组播使用。

2 FCL中实现UDP组播的两种方式

FCL为使用UDP提供了两个类,一个是基础的Socket,一个是封装了Socket的UdpClient。需要说明的是,组播的特殊性只是在接收方才存在,对于发送方,直接向组播IP地址发送即可,与单播无异。

发送程序如下:

class Program    {        private static UdpClient client = new UdpClient(6000);        static void Main(string[] args)        {            byte[] bytes = Encoding.UTF8.GetBytes("hello");            while (true)            {                Thread.Sleep(1000);                client.Send(bytes, bytes.Length, new IPEndPoint(IPAddress.Parse("224.0.0.101"), 6005));            }        }    }

2.1 使用UdpClient

由于UdpClient对Socket进行了很好的封装,所以使用起来比较方便,本身就提供了加入组播组的方法。代码如下:

public class UDPMulticastListener    {        public static void Main(String[] args)        {            UdpClient udpClient = new UdpClient(6005);            udpClient.JoinMulticastGroup(IPAddress.Parse("224.0.0.101"));            IPEndPoint remoteEp = new IPEndPoint(IPAddress.Any, 0);            while (true)            {                Byte[] buffer = udpClient.Receive(ref remoteEp);                String msg = Encoding.UTF8.GetString(buffer);                Console.WriteLine(msg);            }        }    }
MSDN上提醒:调用JoinMulticastGroup之前,必须为udpClient绑定了端口。

2.2 使用Socket

Socket提供了最基础和灵活的控制,需要通过SetSocketOption()方法来加入组播组。代码如下:

public class UDPMulticastListener    {        public static void Main(String[] args)        {            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);            listener.Bind(new IPEndPoint(IPAddress.Any, 6005));            MulticastOption mcastOption = new MulticastOption(IPAddress.Parse("224.0.0.101"), IPAddress.Parse("172.16.35.220"));            listener.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcastOption);            while (true)            {                byte[] buffer = new byte[1024];                int n = listener.Receive(buffer);                String msg = Encoding.UTF8.GetString(buffer, 0, n);                Console.WriteLine(msg);            }        }    }
需要注意的是,指定MulticastOption的时候,必须为其指定要使用网卡源IP地址,否则组播不能成功。

3 抓包分析以太网中UDP组播实现

通过上面实例可以看出,在C#中使用组播非常简单。组播在以太网中是如何实现的呢?
首先,与IP地址一样,以太网中的MAC地址也有一部分专门供组播使用,他们的特征是最高字节的最低位是1,这些MAC地址不能作为网卡的MAC,只能是组播MAC。对这些MAC的处理是这样的:交换机会把目的MAC是组播MAC的包转发到同一VLAN的所有端口,主机上的网卡不仅接收目的MAC是自己Mac的,也接收目的MAC是组播MAC的包,然后把收到的包剥去以太层交给IP层、UDP层继续处理。在IP层,如果发现目的IP是组播IP,并且本机已加入了这个组播组,则交由对应的应用程序处理,否则丢弃。

关于组播IP于组播MAC的对应规则有专门的规定。关于组播有一篇英文妙文,http://www.firewall.cx/networking-topics/general-networking/107-network-multicast.html。