与众不同 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
[源码下载]

时间: 2024-10-26 03:30:01

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

与众不同windows phone (32)

Communication(通信)之任意源组播 ASM(Any Source Multicast) 介绍 与众不同 windows phone 7.5 (sdk 7.1) 之通信 实现"任意源多播" - ASM(Any Source Multicast) 示例 实现 ASM 信道 UdpAnySourceMulticastChannel.cs /* * 实现一个 ASM 信道(即 ASM 帮助类),供外部调用 * * * 通过 UdpAnySourceMulticastClient 实

与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室

原文:与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室 作者:webabcd 介绍与众不同 windows phone 7.5 (sdk 7.1) 之通信 实例 - 基于 Socket TCP 开发一个多人聊天室 示例1.服务端ClientSocketP

与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室

原文:与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室 作者:webabcd 介绍与众不同 windows phone 7.5 (sdk 7.1) 之通信 实例 - 基于 Socket UDP 开发一个多人聊天室 示例1.服务端Main.cs /* *

与众不同 windows phone (29) - Communication(通信)之与 OData 服务通信

原文:与众不同 windows phone (29) - Communication(通信)之与 OData 服务通信 [索引页][源码下载] 与众不同 windows phone (29) - Communication(通信)之与 OData 服务通信 作者:webabcd 介绍与众不同 windows phone 7.5 (sdk 7.1) 之通信 与 OData 服务通信 示例1.服务端(采用 Northwind 示例数据库)NorthwindService.svc.cs /* * 提供

与众不同 windows phone (33) - Communication(通信)之源特定组播 SSM(Source Specific Multicast)

原文:与众不同 windows phone (33) - Communication(通信)之源特定组播 SSM(Source Specific Multicast) [索引页][源码下载] 与众不同 windows phone (33) - Communication(通信)之源特定组播 SSM(Source Specific Multicast) 作者:webabcd 介绍与众不同 windows phone 7.5 (sdk 7.1) 之通信 实现"源特定多播" - SSM(So

与众不同windows phone (33)

Communication(通信)之源特定组播 SSM(Source Specific Multicast) 示例 1.服务端 Main.cs /* * 此服务会定时向指定的多播组发送消息,用于演示 SSM */ using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using

与众不同windows phone (46) 8.0 通信: Socket, 其它

介绍 与众不同 windows phone 8.0 之 通信 Socket Demo 获取当前连接的信息 http rss odata socket bluetooth nfc voip winsock 示例 1.演示 socket tcp 的应用 (本例既做服务端又做客户端) Communication/SocketDemo.xaml <phone:PhoneApplicationPage x:Class="Demo.Communication.SocketDemo" xmln

与众不同 windows phone (46) - 8.0 通信: Socket, 其它

原文:与众不同 windows phone (46) - 8.0 通信: Socket, 其它 [源码下载] 与众不同 windows phone (46) - 8.0 通信: Socket, 其它 作者:webabcd 介绍与众不同 windows phone 8.0 之 通信 Socket Demo 获取当前连接的信息 http rss odata socket bluetooth nfc voip winsock 示例1.演示 socket tcp 的应用(本例既做服务端又做客户端)Com

与众不同windows phone (31)

Communication(通信)之基于 Socket UDP 开发一个多人聊天室 介绍 与众不同 windows phone 7.5 (sdk 7.1) 之通信 实例 - 基于 Socket UDP 开发一个多人聊天室 示例 1.服务端 Main.cs /* * Socket UDP 聊天室的服务端 * * 注:udp 报文(Datagram)的最大长度为 65535(包括报文头) */ using System; using System.Collections.Generic; using