使用 UDP 传输创建多播应用程序

多播应用程序同时向大量收件人发送小消息,而无需建立点到点连接。 此类应用程序的重点是速度超过可靠性。 换句话说,发送及时数据比确保实际接收任何特定消息更重要。 WCF 现在支持使用 UdpBinding 编写多播应用程序。 当服务需要同时向多个客户端发送小消息时,此传输非常有用。 股票行情应用是此类服务的一个示例。

实现多播应用程序

若要实现多播应用程序,请定义服务协定,并为需要响应多播消息的每个软件组件实现服务协定。 例如,股票行情应用程序可以定义服务合同:

// Shared contracts between the client and the service  
[ServiceContract]
interface IStockTicker
{
    [OperationContract(IsOneWay = true)]
    void SendStockInfo(StockInfo[] stockInfo);
}

[DataContract]
class StockInfo
{
    [DataMember]
    public string Symbol;

    [DataMember]
    public float Price;

    public StockInfo(string symbol, float price)
    {
        this.Symbol = symbol;
        this.Price = price;
    }
}

要接收多播消息的每个应用程序都必须承载公开此接口的服务。 例如,下面是演示如何接收多播消息的代码示例:

// Service Address
string serviceAddress = "soap.udp://224.0.0.1:40000";
// Binding
UdpBinding myBinding = new UdpBinding();
// Host
ServiceHost host = new ServiceHost(typeof(StockTickerService), new Uri(serviceAddress));
// Add service endpoint
host.AddServiceEndpoint(typeof(IStockTicker), myBinding, string.Empty);
// Open up the service host
host.Open();

Console.WriteLine("Start receiving stock information");
Console.ReadLine();

应用程序指定所有服务都将侦听的 UDP 地址。 创建一个新的 ServiceHost,并使用 UdpBinding 公开一个服务端点。 然后,ServiceHost 打开并开始侦听传入消息。

在这种情况下,真正发送多播消息的是客户端。 正在正确的 UDP 地址上侦听的每个服务都将接收多播消息。 下面是发送多播消息的客户端的示例:

// Multicast Address
string serviceAddress = "soap.udp://224.0.0.1:40000";

// Binding
UdpBinding myBinding = new UdpBinding();

// Channel factory
ChannelFactory<IStockTicker> factory
    = new ChannelFactory<IStockTicker>(myBinding,
                new EndpointAddress(serviceAddress));

// Call service
IStockTicker proxy = factory.CreateChannel();

while (true)
{
    // This will continue to multicast stock information
    proxy.SendStockInfo(GetStockInfo());
    Console.WriteLine($"sent stock info at {DateTime.Now}");
    // Wait for one second before sending another update
    System.Threading.Thread.Sleep(new TimeSpan(0, 0, 1));
}

此代码将生成股票信息,然后使用服务协定 IStockTicker 发送多播消息,以调用在正确的 UDP 地址上侦听的服务。

UDP 和 可靠消息传递

UDP 绑定不支持可靠的消息传送,因为 UDP 协议的轻型性质。 如果需要确认远程终结点接收消息,请使用支持可靠消息传送(如 HTTP 或 TCP)的传输。 有关可靠消息传送的详细信息,请参阅 https://go.microsoft.com/fwlink/?LinkId=231830

双向多播消息传送

虽然多播消息通常是单向的,但 UdpBinding 支持请求/回复消息交换。 使用 UDP 传输发送的消息同时包含 From 和 To 地址。 使用 From 地址时,必须小心,因为它可能在路由中被恶意更改。 可以使用以下代码检查地址:

if (address.AddressFamily == AddressFamily.InterNetwork)
{
    // IPv4
    byte[] addressBytes = address.GetAddressBytes();
    return ((addressBytes[0] & 0xE0) == 0xE0);
}
else
{
    // IPv6
    return address.IsIPv6Multicast;
}

此代码检查 From 地址的第一个字节,以查看它是否包含0xE0,表示该地址是多转换地址。

安全注意事项

侦听多播消息时,ICMP 数据包会发送到路由器,通知它你正在侦听多播地址。 具有权限的本地子网上的任何人都可以侦听这些类型的数据包,并确定要侦听的多播地址和端口。

不要将发送方的 IP 地址用于任何安全目的。 此信息可能会欺骗,并可能导致应用程序向错误计算机发送响应。 缓解此威胁的一种方法是启用消息级别安全性。 IPSec(互联网协议安全)和/或 NAP(网络访问保护)也可以在网络级别使用。