文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>稳扎稳打Silverlight(55) - 4.0通信之对UDP协议的支持: 通过 UdpSingleSourceMulticastClient 实现 SSM(

稳扎稳打Silverlight(55) - 4.0通信之对UDP协议的支持: 通过 UdpSingleSourceMulticastClient 实现 SSM(

时间:2010-09-27  来源:webabcd

[源码下载]


稳扎稳打Silverlight(55) - 4.0通信之对UDP协议的支持: 通过 UdpSingleSourceMulticastClient 实现 SSM(Source Specific Multicast),即“源特定多播”

作者:webabcd


介绍
Silverlight 4.0 对 UDP 协议的支持:
  • UdpSingleSourceMulticastClient - 一个从单一源接收多播信息的客户端,即 SSM 客户端


在线DEMO
http://www.cnblogs.com/webabcd/archive/2010/08/09/1795417.html


示例
演示如何通过 UdpSingleSourceMulticastClient 实现 SSM
1、服务端
Form1.cs
代码 // 启动用于演示 SSM 的 Socket 服务(基于 UDP 协议)
private void LaunchSocketUdp()
{
    // 服务端的 IPEndPoint
    IPEndPoint serverPoint = new IPEndPoint(IPAddress.Any, 3004);
    // 广播地址的 IPEndPoint(255.255.255.255)
    IPEndPoint broadcastPoint = new IPEndPoint(IPAddress.Broadcast, 3003);

    // 根据服务端的 IPEndPoint 创建服务端的 UDP 对象
    UdpClient serverUdp = new UdpClient(serverPoint);
    ShowMessage("演示 SSM 的 Socket 服务已启动(基于 UDP 协议)");

            
    // 每 3 表广播一次
    var timer = new System.Timers.Timer();
    timer.Interval = 3000d;
    timer.Elapsed += delegate
    {
        string msg = string.Format("{0}: {1} - [{2}]", Dns.GetHostName(), "广播内容", DateTime.Now.ToString("HH:mm:ss"));
        byte[] data = Encoding.UTF8.GetBytes(msg);

        // 发送广播(分别需要指定:广播内容;广播内容的字节数;广播地址的 IPEndPoint)
        serverUdp.Send(data, data.Length, broadcastPoint);
    };
    timer.Start();


    // 接收客户端发过来的信息
    var thread = new System.Threading.Thread(() =>
    {
        while (true)
        {
            IPEndPoint clientPoint = null;
            // 接收客户端传来的信息,并获取客户端的 IPEndPoint
            byte[] receivedBytes = serverUdp.Receive(ref clientPoint);
            string receivedData = Encoding.UTF8.GetString(receivedBytes);
            string message = string.Format("{0} - 来自:{1}", receivedData, clientPoint.ToString());

            _syncContext.Post(delegate { ShowMessage(message); }, null);
        }
    });
    thread.Start();
}

// 启动多播的安全策略服务
private void LaunchMulticastPolicyServer()
{
    /*
        * Silverlight 程序加入多播组之前,会通过 UDP 端口 9430 发送初始消息到多播组,然后服务端返回相应的安全策略(详见文档)
        * 为了方便下发安全策略,可以引用 Microsoft.Silverlight.PolicyServers.dll 程序集,其封装了相关的方法
        */

    // 本例的安全策略配置结果为:授权通过 UDP 端口 3003 问多播组 224.0.0.1,授权通过 UDP 端口 3006 问多播组 224.0.0.1
    MulticastPolicyConfiguration config = new MulticastPolicyConfiguration();
    config.SingleSourceConfiguration.Add("*", new MulticastResource(IPAddress.Parse("224.0.0.1"), 3003)); // 配置 SSM 的安全策略

    MulticastPolicyServer server = new MulticastPolicyServer(config);
    server.Start();

    ShowMessage("多播的安全策略服务已启动");
}


2、客户端
UdpPacketEventArgs.cs 代码 using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Silverlight40.Communication
{
    public class UdpPacketEventArgs : EventArgs
    {
        // UDP 包的内容
        public string Message { get; set; }
        // UDP 包的来源的 IPEndPoint 
        public IPEndPoint Source { get; set; }

        public UdpPacketEventArgs(byte[] data, IPEndPoint source)
        {
            this.Message = System.Text.Encoding.UTF8.GetString(data, 0, data.Length);
            this.Source = source;
        }
    }
}

UdpSingleSourceMulticastChannel.cs 代码 /*
 * 通过 UdpSingleSourceMulticastClient 实现 SSM(Source Specific Multicast),即“源特定多播”
 * 多播组基于 IGMP(Internet Group Management Protocol),即“Internet组管理协议”
 * 
 * UdpSingleSourceMulticastClient - 一个从单一源接收多播信息的客户端,即 SSM 客户端
 *     BeginJoinGroup(), EndJoinGroup() - 加入“源”的异步方法
 *     BeginReceiveFromSource(), EndReceiveFromSource() - 从“源”接收信息的异步方法
 *     BeginSendToSource(), EndSendToSource() - 发送信息到“源”的异步方法
 *     ReceiveBufferSize - 接收信息的缓冲区大小
 *     SendBufferSize - 发送信息的缓冲区大小
 *     
 * 本例为一个通过 UdpSingleSourceMulticastClient 实现 SSM 客户端的帮助类
 */

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

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

namespace Silverlight40.Communication
{
    public class UdpSingleSourceMulticastChannel : IDisposable
    {
        // 多播源的端口
        private int _serverPort = 3004;

        private UdpSingleSourceMulticastClient _client;
        // 接收信息的缓冲区
        private byte[] _buffer;
        // 此客户端是否加入了多播组
        private bool _isJoined;
        // 多播源的地址
        private IPAddress _sourceAddress;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sourceAddress">“源”的地址</param>
        /// <param name="groupAddress">多播组的地址</param>
        /// <param name="port">客户端端口</param>
        /// <param name="maxMessageSize">接收信息的缓冲区大小</param>
        public UdpSingleSourceMulticastChannel(IPAddress sourceAddress, IPAddress groupAddress, int port, int maxMessageSize)
        {
            _sourceAddress = sourceAddress;
            _buffer = new byte[maxMessageSize];
            // 实例化 SSM 客户端,需要指定的参数为:多播源的地址;多播组的地址;客户端端口
            _client = new UdpSingleSourceMulticastClient(sourceAddress, groupAddress, port);
        }

        // 收到多播信息后触发的事件
        public event EventHandler<UdpPacketEventArgs> Received;
        private void OnReceived(IPEndPoint source, byte[] data)
        {
            var handler = Received;
            if (handler != null)
                handler(this, new UdpPacketEventArgs(data, source));
        }

        // 加入多播组后触发的事件
        public event EventHandler Opening;
        private void OnOpening()
        {
            var handler = Opening;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        // 断开多播组后触发的事件
        public event EventHandler Closing;
        private void OnClosing()
        {
            var handler = Closing;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }

        /// <summary>
        /// 加入多播组
        /// </summary>
        public void Open()
        {
            if (!_isJoined)
            {
                _client.BeginJoinGroup(
                    result =>
                    {
                        _client.EndJoinGroup(result);
                        _isJoined = true;
                        Deployment.Current.Dispatcher.BeginInvoke(
                            () =>
                            {
                                OnOpening();
                                Receive();
                            });
                    }, null);
            }
        } 

        public void Close()
        {
            _isJoined = false;
            OnClosing();
            Dispose();
        }

        /// <summary>
        /// 发送信息到“源”
        /// </summary>
        public void Send(string msg)
        {
            if (_isJoined)
            {
                byte[] data = Encoding.UTF8.GetBytes(msg);

                // 需要指定多播源的端口
                _client.BeginSendToSource(data, 0, data.Length, _serverPort,
                    result =>
                    {
                        _client.EndSendToSource(result);
                    }, null);
            }
        }

        /// <summary>
        /// 接收从“源”发过来的广播信息
        /// </summary>
        private void Receive()
        {
            if (_isJoined)
            {
                Array.Clear(_buffer, 0, _buffer.Length);

                _client.BeginReceiveFromSource(_buffer, 0, _buffer.Length,
                    result =>
                    {
                        int sourcePort;
                        // 接收到广播信息后,可获取到“源”的端口
                        _client.EndReceiveFromSource(result, out sourcePort);
                        Deployment.Current.Dispatcher.BeginInvoke(
                            () =>
                            {
                                OnReceived(new IPEndPoint(_sourceAddress, sourcePort), _buffer);
                                Receive();
                            });
                    }, null);
            }
        }

        public void Dispose()
        {
            if (_client != null)
                _client.Dispose();
        }
    }
}

UdpSingleSourceMulticastClientDemo.xaml 代码 <navigation:Page x:Class="Silverlight40.Communication.UdpSingleSourceMulticastClientDemo" 
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
           xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
           Title="UdpSingleSourceMulticastClientDemo Page">
    <Grid x:Name="LayoutRoot">
        
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="80" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="60" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="40" />
        </Grid.RowDefinitions>

        <ListBox Name="lstAllMsg" Grid.ColumnSpan="3" Margin="6" />
        <TextBox Name="txtUserName" Grid.Row="1" Grid.Column="0" Margin="6" />
        <TextBox Name="txtSendMsg" Grid.Row="1" Grid.Column="1" TextWrapping="Wrap" Margin="6" KeyDown="txtMsg_KeyDown" />
        <Button Name="btnSend" Grid.Row="1" Grid.Column="2" Margin="6" Content="发送" Click="btnSend_Click" />
        
    </Grid>
</navigation:Page>

UdpSingleSourceMulticastClientDemo.xaml.cs 代码 /*
 * 用于演示 SSM 的客户端
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;

namespace Silverlight40.Communication
{
    public partial class UdpSingleSourceMulticastClientDemo : Page
    {
        private UdpSingleSourceMulticastChannel _channel;

        public UdpSingleSourceMulticastClientDemo()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            txtUserName.Text = "匿名" + new Random().Next(1000, 9999).ToString();

            _channel = new UdpSingleSourceMulticastChannel(IPAddress.Parse("172.16.100.111"), IPAddress.Parse("224.0.0.1"), 3003, 2048); 
            _channel.Opening += new EventHandler(_channel_Opening);
            _channel.Received += new EventHandler<UdpPacketEventArgs>(_channel_Received);
            _channel.Closing += new EventHandler(_channel_Closing);

            Application.Current.Exit += new EventHandler(Current_Exit);

            _channel.Open();
        }

        void _channel_Opening(object sender, EventArgs e)
        {
            lstAllMsg.Items.Insert(0, "已经连上多播源");
        }

        void _channel_Received(object sender, UdpPacketEventArgs e)
        {
            // 因为已经指定了接收信息的缓冲区大小是 2048 ,所以如果信息不够 2048 个字节的的话,空白处均为“\0”
            string message = string.Format("{0} - 来自:{1}", e.Message.TrimEnd('\0'), e.Source.ToString()); 
            lstAllMsg.Items.Insert(0, message);
        }

        void _channel_Closing(object sender, EventArgs e)
        {
            lstAllMsg.Items.Insert(0, "已经断开多播源");
        }

        void Current_Exit(object sender, EventArgs e)
        {
            _channel.Dispose();
        }

        private void btnSend_Click(object sender, RoutedEventArgs e)
        {
            SendMsg();
        }

        private void txtMsg_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
                SendMsg();
        }

        private void SendMsg()
        {
            _channel.Send(string.Format("{0}: {1} - [{2}]", txtUserName.Text, txtSendMsg.Text, DateTime.Now.ToString("HH:mm:ss")));
            txtSendMsg.Text = "";
        }
    }
}


OK
[源码下载]
相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载