与众不同 windows phone (32) - Communication(通信)之任意源组播 ASM(Any Source Multicast)

原文: 与众不同 windows phone (32) - Communication(通信)之任意源组播 ASM(Any Source Multicast)

[索引页]
[源码下载]


与众不同 windows phone (32) - Communication(通信)之任意源组播 ASM(Any Source Multicast)



作者:webabcd


介绍
与众不同 windows phone 7.5 (sdk 7.1) 之通信

  • 实现“任意源多播” - ASM(Any Source Multicast)



示例
实现 ASM 信道
UdpAnySourceMulticastChannel.cs

/*

 * 实现一个 ASM 信道(即 ASM 帮助类),供外部调用

 * 

 * 

 * 通过 UdpAnySourceMulticastClient 实现 ASM(Any Source Multicast),即“任意源多播”

 * 多播组基于 IGMP(Internet Group Management Protocol),即“Internet组管理协议”

 * 

 * UdpAnySourceMulticastClient - 一个发送信息到多播组并从任意源接收多播信息的客户端,即 ASM 客户端

 *     BeginJoinGroup(), EndJoinGroup() - 加入多播组的异步方法

 *     BeginReceiveFromGroup(), EndReceiveFromGroup() - 从多播组接收信息的异步方法(可以理解为接收多播组内所有成员发送的信息)

 *     BeginSendToGroup(), EndSendToGroup() - 发送信息到多播组的异步方法(可以理解为发送信息到多播组内的全部成员)

 *     ReceiveBufferSize - 接收信息的缓冲区大小

 *     SendBufferSize - 发送信息的缓冲区大小

 *     

 *     BeginSendTo(), EndSendTo() - 发送信息到指定目标的异步方法

 *     BlockSource() - 阻止指定源,以便不再接收该源发来的信息

 *     UnblockSource() - 取消阻止指定源

 *     MulticastLoopback - 发出的信息是否需要传给自己

 * 

 */



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 Demo.Communication.SocketClient

{

    public class UdpAnySourceMulticastChannel : IDisposable

    {

        // ASM 客户端

        private UdpAnySourceMulticastClient _client;



        // 接收信息的缓冲区

        private byte[] _buffer;

        // 此客户端是否加入了多播组

        private bool _isJoined;



        /// <summary>

        /// 构造函数

        /// </summary>

        /// <param name="groupAddress">多播组地址</param>

        /// <param name="port">多播组的端口</param>

        /// <param name="maxMessageSize">接收信息的缓冲区大小</param>

        /// <remarks>

        /// 注:udp 报文(Datagram)的最大长度为 65535(包括报文头)

        /// </remarks>

        public UdpAnySourceMulticastChannel(IPAddress groupAddress, int port, int maxMessageSize)

        {

            _buffer = new byte[maxMessageSize];

            // 实例化 ASM 客户端,需要指定的参数为:多播组地址;多播组的端口

            _client = new UdpAnySourceMulticastClient(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);

            }

        }



        /// <summary>

        /// 发送信息到多播组,即发送信息到多播组内的所有成员

        /// </summary>

        public void Send(string msg)

        {

            if (_isJoined)

            {

                byte[] data = Encoding.UTF8.GetBytes(msg);



                _client.BeginSendToGroup(data, 0, data.Length,

                    result =>

                    {

                        _client.EndSendToGroup(result);

                    }, null);

            }

        }



        /// <summary>

        /// 从多播组接收信息,即接收多播组内所有成员发送的信息

        /// </summary>

        private void Receive()

        {

            if (_isJoined)

            {

                Array.Clear(_buffer, 0, _buffer.Length);



                _client.BeginReceiveFromGroup(_buffer, 0, _buffer.Length,

                    result =>

                    {

                        IPEndPoint source;

                        _client.EndReceiveFromGroup(result, out source);

                        Deployment.Current.Dispatcher.BeginInvoke(

                            () =>

                            {

                                OnReceived(source, _buffer);

                                Receive();

                            });

                    }, null);

            }

        }



        // 关闭 ASM 信道

        public void Close()

        {

            _isJoined = false;

            OnClosing();

            Dispose();

        }



        public void Dispose()

        {

            if (_client != null)

                _client.Dispose();

        }

    }

}


演示 ASM
AnySourceMulticast.xaml

<phone:PhoneApplicationPage 

    x:Class="Demo.Communication.SocketClient.AnySourceMulticast"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"

    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    FontFamily="{StaticResource PhoneFontFamilyNormal}"

    FontSize="{StaticResource PhoneFontSizeNormal}"

    Foreground="{StaticResource PhoneForegroundBrush}"

    SupportedOrientations="Portrait" Orientation="Portrait"

    mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"

    shell:SystemTray.IsVisible="True">



    <Grid x:Name="LayoutRoot" Background="Transparent">

        <StackPanel HorizontalAlignment="Left">



            <ListBox Name="lstAllMsg" MaxHeight="400" />

            <TextBox x:Name="txtName" />

            <TextBox x:Name="txtInput" KeyDown="txtInput_KeyDown" />

            <Button x:Name="btnSend" Content="发送" Click="btnSend_Click" />



        </StackPanel>        

    </Grid>



</phone:PhoneApplicationPage>

AnySourceMulticast.xaml.cs

/*

 * 用于演示 ASM

 */



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 Microsoft.Phone.Controls;



using System.Windows.Navigation;



namespace Demo.Communication.SocketClient

{

    public partial class AnySourceMulticast : PhoneApplicationPage

    {

        // 实例化自定义的 ASM 信道

        private UdpAnySourceMulticastChannel _channel;



        public AnySourceMulticast()

        {

            InitializeComponent();

        }



        protected override void OnNavigatedTo(NavigationEventArgs e)

        {

            txtName.Text = "匿名" + new Random().Next(1000, 9999).ToString();



            // 多播组地址是必须介于 224.0.0.0 到 239.255.255.255 之间的 IP 地址,其中范围介于 224.0.0.0 到 224.0.0.255 之间的多播地址是保留多播地址

            // 比如:224.0.0.0 是基址,224.0.0.1 是代表同一个物理网络中所有系统的多播组地址,而 224.0.0.2 代表同一个物理网络中的所有路由器

            _channel = new UdpAnySourceMulticastChannel(IPAddress.Parse("224.0.1.1"), 3368, 2048); 

            _channel.Opening += new EventHandler(_channel_Opening);

            _channel.Received += new EventHandler<UdpPacketEventArgs>(_channel_Received);

            _channel.Closing += new EventHandler(_channel_Closing);



            _channel.Open();



            // 需要的使用,应该调用 Close()

            // _channel.Close();

        }



        void _channel_Opening(object sender, EventArgs e)

        {

            _channel.Send(string.Format("{0}: 进来了 - [{1}]", txtName.Text, DateTime.Now.ToString("HH:mm:ss")));

        }



        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)

        {

            _channel.Send(string.Format("{0}: 离开了 - [{1}]", txtName.Text, DateTime.Now.ToString("HH:mm:ss")));

        }



        private void btnSend_Click(object sender, RoutedEventArgs e)

        {

            SendMsg();

        }



        private void txtInput_KeyDown(object sender, KeyEventArgs e)

        {

            if (e.Key == Key.Enter)

            {

                SendMsg();

                this.Focus();

            }

        }



        private void SendMsg()

        {

            _channel.Send(string.Format("{0}: {1} - [{2}]", txtName.Text, txtInput.Text, DateTime.Now.ToString("HH:mm:ss")));

            txtInput.Text = "";

        }

    }

}



OK
[源码下载]

你可能感兴趣的:(windows phone)