Windows Phone学习笔记(9) — — 多播套接字
本次我们来做一个多播套接字的示例。首先是页面的效果图。
页面由一个ListBox、一个文本框和按钮构成。代码如下:
View Code
<!--LayoutRoot 是包含所有页面内容的根网格--> <Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!--TitlePanel 包含应用程序的名称和页标题--> <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28"> <TextBlock x:Name="ApplicationTitle" Text="BasicUDPMulticastClient" Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock x:Name="PageTitle" Text="messages" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> </StackPanel> <!--ContentPanel - 在此处放置其他内容--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Grid.RowDefinitions> <RowDefinition Height="500"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <ListBox x:Name="lbLog" Height="500" BorderBrush="{StaticResource PhoneForegroundBrush}" BorderThickness="5" Background="{StaticResource PhoneDisabledBrush}" /> <StackPanel Grid.Row="1" Orientation="Horizontal"> <TextBlock Text="Text To Send" VerticalAlignment="Center"/> <TextBox x:Name="txtInput" Width="200"/> <Button x:Name="btnSend" Width="150" Content="Send" Click="btnSend_Click"/> </StackPanel> </Grid> </Grid>
我们通过Send按钮的单击事件把数据发送到多播组:
private void btnSend_Click(object sender, RoutedEventArgs e) { if (!String.IsNullOrWhiteSpace(txtInput.Text)) { Send(txtInput.Text); } }
下面是向ListBox控件显示发送和接收数据的消息记录:
View Code
private void Log(string message, bool isOutgoing) { if (string.IsNullOrWhiteSpace(message.Trim('\0'))) return; Deployment.Current.Dispatcher.BeginInvoke( () => { string direction = (isOutgoing) ? ">> " : "<< "; string timestamp = DateTime.Now.ToString("HH:mm:ss"); message = timestamp + direction + message; lbLog.Items.Add(message); lbLog.ScrollIntoView(message); }); }
在MainPage.xaml.cs文件的顶部声明一下几个变量:
View Code
// 多播组加入的地址。 // 地址的范围必须在从224.0.0.0到239.255.255.255之间 private const string GROUP_ADDRESS = "224.0.1.1"; //在多播组上通信的端口 private const int GROUP_PORT = 52274; //从任何来源接收多播流量的客户端 UdpAnySourceMulticastClient _client = null; //如果我们确实已经加入了组播组,则为true,否则为false bool _joined = false; //缓冲传入的数据 private byte[] _receiveBuffer; //最大的消息通信数量 private const int MAX_MESSAGE_SIZE = 512;
这里用到了UdpAnySourceMulticastClient类,UdpAnySourceMulticastClient类封装了通过 UDP 与多播组通信所需的逻辑。
View Code
/// <summary> /// 重写OnNavigatedTo方法 /// </summary> protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { base.OnNavigatedTo(e); //创建一个新的UdpAnySourceMulticastClient实例和加入这个多播组。 Join(); } /// <summary> /// 创建一个新的UdpAnySourceMulticastClient实例和加入这个多播组。 /// </summary> private void Join() { //初始化接收缓冲区 _receiveBuffer = new byte[MAX_MESSAGE_SIZE]; //创建UdpAnySourceMulticastClient实例使用定义的组地址和组端口常量。 //UdpAnySourceMulticastClient是一个客户端接收机的多播流量从任何来源,也被称为任何源多播(ASM) _client = new UdpAnySourceMulticastClient(IPAddress.Parse(GROUP_ADDRESS), GROUP_PORT); //请求加入该多播组。 _client.BeginJoinGroup( result => { //完成加入 _client.EndJoinGroup(result); //这个MulticastLoopback属性控制你是否收到多播包你发送到多播组 _client.MulticastLoopback = true; //设置一个标志,指示我们现在已经加入多播组 _joined = true; // 让别人知道我们已经加入了发送消息到一个组。 Send("Joined the group"); //从组中等待数据。这是一个异步进程不会阻碍UI进程 Receive(); }, null); }
之后是多播组数据的发送和接收:
View Code
/// <summary> /// 发送特定消息到多播组。 /// </summary> /// <param name="message">要发送的信息</param> private void Send(string message) { //如果你已经加入到这个组中,尝试发送 if (_joined) { byte[] data = Encoding.UTF8.GetBytes(message); _client.BeginSendToGroup(data, 0, data.Length, result => { _client.EndSendToGroup(result); //我们发送的日志 Log(message, true); },null); } else { Log("Message was not sent since you are not joined to the group", true); } } /// <summary> /// 接收数据组和进行日志记录 /// </summary> private void Receive() { //只有尝试接收如果你已经加入了这个组 if (_joined) { Array.Clear(_receiveBuffer, 0, _receiveBuffer.Length); _client.BeginReceiveFromGroup(_receiveBuffer, 0, _receiveBuffer.Length, result => { IPEndPoint source; //完成异步操作。在发送的源字段信息中包含设备的IP地址 _client.EndReceiveFromGroup(result, out source); //获得将接收的数据从缓冲。 string dataReceived = Encoding.UTF8.GetString(_receiveBuffer, 0, _receiveBuffer.Length); //创建一个日志条目。 string message = String.Format("[{0}]: {1}", source.Address.ToString(), dataReceived); //记录日志 Log(message, false); //调用接收再继续来“听”下一条消息的组 Receive(); }, null); } else { Log("Cannot receive. You are currently not joined to the group", true); } }
虽然是MSDN的一个代码示例,但是也展示了多播组的基本操作。
参考地址:http://msdn.microsoft.com/zh-cn/library/hh286407(v=vs.92).aspx