文章目录

  • 组播的概念
  • 简单示例
  • 组播的优势


组播的概念

UDP信息传递的方式分三类,分别是

  • 单播 Unicast:客户端与服务器之间的点到点连接
  • 多播MultiCast:又称组播,是“一对一组”的通讯模式,加入同一个组的主机可以接受到此组内的所有数据。
  • 广播 BroadCast:主机之间“一对所有”的通讯模式,广播者可以向网络中所有主机发送信息。广播禁止在Internet宽带网上传输。

其中单播比较简单,在C#中可直接通过UdpClient点对点收发。

组播和单播的差别是,必须得有一个“组”的概念,然后才能进行组播,在C#中,通过client.JoinMulticastGroup来实现。

另外,组播对IP地址的范围有一定的要求:

起始IP

截至IP

适用范围

224.0.0.1

224.0.0.255

预留地址,最好不要乱用

224.0.1.0

224.0.1.255

公用地址,可用于互联网

224.0.2.0

238.255.255.255

用户可用,全网范围

239.0.0.0

239.255.255.255

本地

其中224.0.0.0也是预留的组播地址,但保留不做分配。

简单示例

下面再顶级语句中做一个简单的示例

using System.Net;
using System.Net.Sockets;
using System.Text;

static void Main()
{
    UdpClient client = new UdpClient(5566);
    client.JoinMulticastGroup(IPAddress.Parse("235.5.6.8"));
    
    IPEndPoint multicast = new IPEndPoint(IPAddress.Parse("234.5.6.7"), 7788);
    byte[] buf = Encoding.Default.GetBytes("Hello from multicast");
    Thread t = new Thread(new ThreadStart(RecvThread));
    t.IsBackground = true;
    t.Start();
    while (true)
    {
        client.Send(buf, buf.Length, multicast);
        Thread.Sleep(1000);
    }
}

static void RecvThread()
{
    UdpClient client = new UdpClient(7788);
    client.JoinMulticastGroup(IPAddress.Parse("234.5.6.7"));
    IPEndPoint multicast = new IPEndPoint(IPAddress.Parse("235.5.6.8"), 5566);
    while (true)
    {
        byte[] buf = client.Receive(ref multicast);
        string msg = Encoding.Default.GetString(buf);
        Console.WriteLine(msg);
    }
}

Main();

函数RecvThread中,定义了一个端口号为7778的UDP客户端,并通过JoinMulticastGroup添加了234.5.6.7这个IP地址。在死循环中,让client不断接收来自multicast的信息,其中multicast是地址为235.5.6.8,端口为5566的终端。

Main函数则创建了端口为5566的客户端,然后不断地向234.5.6.7:7788发送消息。

这个示例程序运行之后,命令行中会不断地输出

Hello from multicast

但这个示例其实并没有体现出“组播”的特点,原因在于上面的代码只用了一个地址,虽然用到了组播的模式,但实际操作上来看,还是一对一的。

组播的优势

下面稍微修改一下代码,首先在RecvThread中新增一个IP

client.JoinMulticastGroup(IPAddress.Parse("234.5.6.9"));

然后在Main中新增一组发给新IP的信息,类似下面这样

static void Main()
{
    UdpClient client = new UdpClient(5566);
    client.JoinMulticastGroup(IPAddress.Parse("235.5.6.8"));
    
    IPEndPoint multi1 = new IPEndPoint(IPAddress.Parse("234.5.6.7"), 7788);
    IPEndPoint multi2 = new IPEndPoint(IPAddress.Parse("234.5.6.9"), 7788);
    byte[] buf1 = Encoding.Default.GetBytes("Hello multi1");
    byte[] buf2 = Encoding.Default.GetBytes("Hello multi2");
    Thread t = new Thread(new ThreadStart(RecvThread));
    t.IsBackground = true;
    t.Start();
    while (true)
    {
        client.Send(buf1, buf1.Length, multi1);
        client.Send(buf2, buf2.Length, multi2);
        Thread.Sleep(1000);
    }
}

从而命令行输出就会变成

Hello multi1
Hello multi2

也就是说,发给两个不同IP地址的信息,都被client接收到了。