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

posted on 2012-12-06 22:30  松竹柏柳  阅读(240)  评论(0编辑  收藏  举报

导航