与众不同 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(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 System.Text;
using System.Windows.Forms;

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

namespace SocketServerSSM
{
    public partial class Main : Form
    {
        System.Threading.SynchronizationContext _syncContext;

        public Main()
        {
            InitializeComponent();

            LaunchSocketUdp();
        }

        private void LaunchSocketUdp()
        {
            _syncContext = System.Threading.SynchronizationContext.Current;

            // 定义 Source Specific Multicast 中的 Source,即 SSM 客户端仅接收此 Source 发送到多播组的数据
            IPEndPoint sourcePoint = new IPEndPoint(IPAddress.Any, 3370);

            // 定义多播组
            IPEndPoint multicastPoint = new IPEndPoint(IPAddress.Parse("224.0.1.2"), 3369);

            UdpClient sourceUdp = new UdpClient(sourcePoint);
            ShowMessage("用于演示 SSM 的 Socket 服务已启动,每 3 秒向多播组发送一次信息");

            // 每 3 秒向多播组发送一次信息
            var timer = new System.Timers.Timer();
            timer.Interval = 3000d;
            timer.Elapsed += delegate
            {
                string msg = string.Format("{0} - {1}", Dns.GetHostName(), DateTime.Now.ToString("HH:mm:ss"));
                byte[] data = Encoding.UTF8.GetBytes(msg);

                sourceUdp.Send(data, data.Length, multicastPoint);
            };
            timer.Start();
        }

        public void ShowMessage(string msg)
        {
            txtMsg.Text += msg + "\r\n";
        }
    }
}

 

2、客户端
实现 SSM 信道
UdpSingleSourceMulticastChannel.cs

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

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.Net.Sockets;
using System.Text;

namespace Demo.Communication.SocketClient
{
    public class UdpSingleSourceMulticastChannel : IDisposable
    {
        // SSM 客户端
        private UdpSingleSourceMulticastClient _client;

        // “源”的地址
        private IPAddress _sourceAddress;

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

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sourceAddress">SSM 的“源”的地址</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);
            }
        }

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

                // 需要指定“源”的端口
                int sourcePort = 100;
                _client.BeginSendToSource(data, 0, data.Length, sourcePort,
                    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);
            }
        }

        // 关闭 SSM 信道
        public void Close()
        {
            _isJoined = false;
            OnClosing();
            Dispose();
        }

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

演示 SSM
SourceSpecificMulticast.xaml

<phone:PhoneApplicationPage
    x:Class="Demo.Communication.SocketClient.SourceSpecificMulticast"
    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" />

        </StackPanel>
    </Grid>

</phone:PhoneApplicationPage>

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

using System.Windows.Navigation;

namespace Demo.Communication.SocketClient
{
    public partial class SourceSpecificMulticast : PhoneApplicationPage
    {
        // 实例化自定义的 SSM 信道
        private UdpSingleSourceMulticastChannel _channel;

        public SourceSpecificMulticast()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            // 多播组地址是必须介于 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 UdpSingleSourceMulticastChannel(IPAddress.Parse("192.168.8.217"), IPAddress.Parse("224.0.1.2"), 3369, 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)
        {
            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, "已经断开多播组");
        }
    }
}

OK
[源码下载]

时间: 2024-09-08 00:58:01

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

与众不同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 (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 (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 M

与众不同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 (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 (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