与众不同 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, ); // 定义多播组
IPEndPoint multicastPoint = new IPEndPoint(IPAddress.Parse("224.0.1.2"), ); 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 = ;
_client.BeginSendToSource(data, , data.Length, sourcePort,
result =>
{
_client.EndSendToSource(result);
}, null);
}
} /// <summary>
/// 接收从多播组发过来的信息,即“源”发送给多播组的信息
/// </summary>
private void Receive()
{
if (_isJoined)
{
Array.Clear(_buffer, , _buffer.Length); _client.BeginReceiveFromSource(_buffer, , _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"), , );
_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(, "已经连上多播组,等待来自多播组的消息");
} 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(, message);
} void _channel_Closing(object sender, EventArgs e)
{
lstAllMsg.Items.Insert(, "已经断开多播组");
}
}
}
OK
[源码下载]
与众不同 windows phone (33) - Communication(通信)之源特定组播 SSM(Source Specific Multicast)的更多相关文章
- 源特定组播(SSM:Source Specific Multicast)
源特定组播(SSM:Source Specific Multicast)是一种区别于传统组播的新的业务模型,它使用组播组地址和组播源地址同时来标识一个组播会话,而不是向传统的组播服务那样只使用组播组地 ...
- 与众不同 windows phone (32) - Communication(通信)之任意源组播 ASM(Any Source Multicast)
原文:与众不同 windows phone (32) - Communication(通信)之任意源组播 ASM(Any Source Multicast) [索引页][源码下载] 与众不同 wind ...
- 与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室
原文:与众不同 windows phone (31) - Communication(通信)之基于 Socket UDP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...
- 与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室
原文:与众不同 windows phone (30) - Communication(通信)之基于 Socket TCP 开发一个多人聊天室 [索引页][源码下载] 与众不同 windows phon ...
- 与众不同 windows phone (29) - Communication(通信)之与 OData 服务通信
原文:与众不同 windows phone (29) - Communication(通信)之与 OData 服务通信 [索引页][源码下载] 与众不同 windows phone (29) - Co ...
- 与众不同 windows phone (46) - 8.0 通信: Socket, 其它
[源码下载] 与众不同 windows phone (46) - 8.0 通信: Socket, 其它 作者:webabcd 介绍与众不同 windows phone 8.0 之 通信 Socket ...
- 与众不同 windows phone 8.0 & 8.1 系列文章索引
[源码下载] [与众不同 windows phone 7.5 (sdk 7.1) 系列文章索引] 与众不同 windows phone 8.0 & 8.1 系列文章索引 作者:webabcd ...
- 为应用程序池“XX”提供服务的进程在与 Windows Process Activation Service 通信时出现严重错误
场景 WCF应用程序部署在IIS7中,使用net.tcp协议对外给几百台客户端提供服务,应用程序池不断崩溃重启. 分析过程 在事件查看器中看到的错误信息类似于 为应用程序池“XX”提供服务的进程在与 ...
- 背水一战 Windows 10 (33) - 控件(选择类): ListBox, RadioButton, CheckBox, ToggleSwitch
[源码下载] 背水一战 Windows 10 (33) - 控件(选择类): ListBox, RadioButton, CheckBox, ToggleSwitch 作者:webabcd 介绍背水一 ...
随机推荐
- 高级UIKit-06(UIImagePickerController)
[day07-1-getSystemImage]:获取系统相册 UIImagePickerController图片采集控制器 picker采集者,采摘者 该方法继承自:UINavigationCont ...
- Linux中处理需要传输的IP报文流程
本文主要讲解了Linux中处理需要传输的IP报文流程,使用的内核的版本是2.6.32.27 为了方便理解,本文采用整体流程图加伪代码的方式对Linux中处理需要传输的IP报文流程进行了讲解,希望可以对 ...
- BZOJ 3173: [Tjoi2013]最长上升子序列( BST + LIS )
因为是从1~n插入的, 慢插入的对之前的没有影响, 所以我们可以用平衡树维护, 弄出最后的序列然后跑LIS就OK了 O(nlogn) --------------------------------- ...
- OCP-1Z0-042-V12.39-51题
51.Which two statements regarding archive log destinations are true? 题目解析: A(正确)因为:.归档日志最多可以配置10个 B和 ...
- Sting和StringBuffer的区别
java.lang.String代表不可变序列: s1 = "hello"; s2 = "world"; s1 = s1 + s2; 内存分配情况是s1有块内存 ...
- notepad++ 配置笔记
0.notepad++简单介绍 Notepad++是一套很有特色的自由软件的纯文字编辑器,有完整的中文化接口及支援多国语言撰写的功能.它的功能比 Windows 中的 Notepad更强大.Notep ...
- 1数组的join方法
function log(e) { console.log(e) } 有时候写console.log太长了,所以会自己写个这样的函数省去写console的步骤. 数组的join方法可以把一个数组按照j ...
- GitHub详解(转)
GitHub 是一个共享虚拟主机服务,用于存放使用Git版本控制的软件代码和内容项目.它由GitHub公司(曾称Logical Awesome)的开发者Chris Wanstrath.PJ Hyett ...
- xxx==null和xxx.equals(null)的区别
如果xxx不是null的话,xxx==null将返回false,如果xxx是null的话,xxx将返回ture 而对xxx.equals(null)而言,他将永远返回false,因为如果xxx不是nu ...
- DBA 应该要注意Linux 环境下的一些操作
DBA 对OS的依赖.一丁点儿也不亚于DB.对于Oracle DBA.尤为突出 DB和OS的感情也与日俱增.耦合度高的让人一度以为这两要劳燕双飞了 例如.Oracle里面. 而且.故障诊断以及 ...