方法: Windows Phone のマルチキャスト グループでデータを送受信する

2012/02/09

このトピックでは、マルチキャスト グループを介した通信方法について説明します。マルチキャスト トラフィックは、インターネット上の多対多間で通信するための拡張性のある方法です。通信は、マルチキャスト グループ アドレスとして知られる IP アドレスによってそれぞれ識別されるマルチキャスト グループ内で行われます。デバイスは、マルチキャスト グループ アドレスをサブスクライブします。その後、マルチキャスト グループにサブスクライブされているデバイスによって送信されたパケットは、マルチキャスト アドレスをサブスクライブしている他のすべてのデバイスによって受信されます。このトピックでは、Windows Phone OS 7.1 で、System.Net.Sockets 名前空間で使用可能な UdpAnySourceMulticastClient クラスを使用して、マルチキャスト グループに参加するために必要な手順を説明します。この機能を示すアプリケーションの完成したサンプルをダウンロードできます。詳細については、「マルチキャスト ソケットのサンプル」を参照してください。

このトピックは、次のセクションで構成されています。

このセクションでは、UDP マルチキャスト機能を示すための UI を作成します。これは Silverlight for Windows Phone アプリケーションです。アプリケーションが起動すると、マルチキャスト グループに参加します。アプリケーションはグループに参加すると、マルチキャスト グループに送信されたメッセージを受信したり、マルチキャスト グループにメッセージを送信したりすることができます。UI にはマルチキャスト グループに送信されたすべてのデータが表示されます。メッセージを入力し、それをマルチキャスト グループに送信することもできます。

ユーザー インターフェイスを作成するには

  1. Visual Studio 2010 Express for Windows Phone で、[ファイル] メニューの [新しいプロジェクト] をクリックして新しいプロジェクトを作成します。

  2. [新しいプロジェクト] ウィンドウが表示されます。Visual C# のテンプレートを展開してから、Silverlight for Windows Phone のテンプレートを選択します。

  3. Windows Phone アプリケーション テンプレートを選択します。[名前] に選択した名前を入力します。

  4. [OK] をクリックします。Windows Phone の [プラットフォームの選択] ウィンドウが表示されます。[Windows Phone OS のターゲット バージョン] の [Windows Phone OS 7.1] を選択します。

    GetStartedSelectPlatformXNA
  5. [OK] をクリックします。新しいプロジェクトが作成され、Visual Studio のデザイナー ウィンドウに MainPage.xaml が表示されます。

  6. MainPage.xaml の中で、"LayoutRoot" という名前の Grid の XAML コードを削除し、次に示すコードで置き換えます。

    
         <Grid x:Name="LayoutRoot" Background="Transparent">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
    
            <!--TitlePanel contains the name of the application and page title-->
            <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 - place additional content here-->
            <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>
    
    
    

    上記の XAM コードでは、次のスクリーンショットのような簡単なユーザー インターフェイスが作成されます。

    基本の UDP マルチキャスト クライアントの方法のスクリーンショット

    イベント ハンドラー btnSend_Click については、以下のセクションで説明します。

  7. データをマルチキャスト グループに送信するため、アプリケーションは TextBox を使用して、ユーザーからのテキストを受け付け、ボタンがクリックされると、TextBox 内のテキストをマルチキャスト グループに送信します。btnSend_Click イベントが発生するため、イベント ハンドラーを分離コード ファイルに追加してこのイベントを処理します。ソリューション エクスプローラーで、MainPage.xaml を右クリックしてから、[コードの表示] をクリックします。コード エディターに分離コード ファイルが開きます。ページの分離コード ファイルの一番上に、次のメソッドを追加します。

    
            /// <summary>
            /// Send whatever the user has typed into the input textbox to the multicast group.
            /// </summary>
            private void btnSend_Click(object sender, RoutedEventArgs e)
            {
                // Don't send empty messages.
                if (!String.IsNullOrWhiteSpace(txtInput.Text))
                {
                    Send(txtInput.Text);
                }
            }
    
    
    

    このメソッドは、最初に入力テキスト ボックスにテキストが含まれていることを確認し、Send メソッドを呼び出し、送信するテキストを渡して、マルチキャスト グループにデータを送信します。Send メソッドについては、以下のセクションで説明します。

  8. マルチキャスト グループで送受信されるメッセージを表示するために、ユーザー インターフェイスに lbLog という ListBox が含まれています。次のコードを使用して、受信されたメッセージを ListBox に追加します。ソリューション エクスプローラーで、MainPage.xaml を右クリックして、[コードの表示] をクリックします。コード エディターに分離コード ファイルが開きます。ページの分離コード ファイルの一番上に、次のメソッドを追加します。

    
            /// <summary>
            /// Log text to the lbLog ListBox.
            /// </summary>
            /// <param name="message">The message to write to the lbLog ListBox</param>
            /// <param name="isOutgoing">True if the message is an outgoing (client to server) message; otherwise, False</param>
            /// <remarks>We differentiate between a message from the client and server 
            /// by prepending each line  with ">>" and "<<" respectively.</remarks>
            private void Log(string message, bool isOutgoing)
            {
                if (string.IsNullOrWhiteSpace(message.Trim('\0')))
                    return;
    
                // Always make sure to do this on the UI thread.
                Deployment.Current.Dispatcher.BeginInvoke(
                () =>
                {
                    string direction = (isOutgoing) ? ">> " : "<< ";
                    string timestamp = DateTime.Now.ToString("HH:mm:ss");
                    message = timestamp + direction + message;
                    lbLog.Items.Add(message);
    
                    // Make sure that the item we added is visible to the user.
                    lbLog.ScrollIntoView(message);
                });
                
            }
    
    

    上記のメソッドでは、メッセージ文字列と、ログに記録されるメッセージがこのデバイスへの着信メッセージであるか、発信メッセージ、つまり、このデバイスが送信したメッセージであるかどうかを示す値を受け付けます。このメッセージは、方向インジケーターとタイムスタンプを含むように変更されます。次にリストボックスに追加され、最後にログに記録されたメッセージをユーザーがいつでも確認できるようにスクロール形式で表示されます。これらのすべての UI 処理は、それらが常に UI スレッドで実行されるように BeginInvoke にラップされます。この例には UI スレッドとは異なるスレッドで実行する非同期操作が含まれるため、この処理は安全のための措置です。

このセクションでは、マルチキャスト グループに参加して、そのグループでデータを送受信できるようにします。

マルチキャスト グループに参加するには

  1. ソリューション エクスプローラーで、MainPage.xaml を右クリックしてから、[コードの表示] をクリックします。コード エディターに分離コード ファイルが開きます。ページの分離コード ファイルの一番上に次のステートメントを追加します。

    
    using System.Net.Sockets;
    using System.Text;
    
  2. MainPage クラスの先頭に、次のメンバーを定義します。

    
            // The address of the multicast group to join.
            // Must be in the range from 224.0.0.0 to 239.255.255.255
            private const string GROUP_ADDRESS = "224.0.1.1";
    
            // The port over which to communicate to the multicast group
            private const int GROUP_PORT = 52274;
    
            // A client receiver for multicast traffic from any source
            UdpAnySourceMulticastClient _client = null;
    
            // true if we have joined the multicast group; otherwise, false
            bool _joined = false;
    
            // Buffer for incoming data
            private byte[] _receiveBuffer;
    
            // Maximum size of a message in this communication
            private const int MAX_MESSAGE_SIZE = 512;
    
    

    上記のコードに関して、次の点に注意する必要があります。

    • GROUP_ADDRESS: マルチキャスト グループはマルチキャスト グループ アドレスによって定義します。このアドレスは、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 は同じ物理ネットワーク上のすべてのルーターを表します。

      注注:

      IANA (Internet Assigned Numbers Authority) は、この予約済みアドレスのリストを担当します。予約済みアドレスの割り当ての詳細については、IANA Web サイトを参照してください。

    • GROUP_PORT: これは、マルチキャスト グループで行われるすべての通信で経由するポート番号を定義します。繰り返しますが、この例の値は任意で、独自の値を自由に選択できます。

    • UdpAnySourceMulticastClient: このクラスは Windows Phone OS 7.1 で使用でき、UDP によるマルチキャスト グループとの通信に必要なロジックをカプセル化します。この例では、このクラスのインスタンスを作成し、Join メソッド、Send メソッド、Receive メソッドで使用します。単一のソースからのマルチキャスト トラフィックの受信については、「UdpSingleSourceMulticastClient」を参照してください。

  3. アプリケーションが起動したら、すぐにマルチキャスト グループに参加し、データの受信を開始します。この例では、OnNavigatedTo メソッドでこの参加アクションを実行します。MainPage クラスに次のメソッドを追加します。

    
            /// <summary>
            /// Override the OnNavigatedTo method.
            /// </summary>
            protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
            {
                base.OnNavigatedTo(e);
    
                // Create a new UdpAnySourceMulticastClient instance and join the group.
                Join();
            }
    
    
  4. MainPage クラスに次のメソッドを追加します。

    
            /// <summary>
            /// Create a new UdpAnySourceMulticastClient instance and join the group.
            /// </summary>
            private void Join()
            {
                // Initialize the receive buffer
                _receiveBuffer = new byte[MAX_MESSAGE_SIZE];
    
                // Create the UdpAnySourceMulticastClient instance using the defined 
                // GROUP_ADDRESS and GROUP_PORT constants. UdpAnySourceMulticastClient is a 
                // client receiver for multicast traffic from any source, also known as Any Source Multicast (ASM)
                _client = new UdpAnySourceMulticastClient(IPAddress.Parse(GROUP_ADDRESS), GROUP_PORT);
    
                // Make a request to join the group.
                _client.BeginJoinGroup(
                    result =>
                    {
                        // Complete the join
                        _client.EndJoinGroup(result);
    
                        // The MulticastLoopback property controls whether you receive multicast 
                        // packets that you send to the multicast group. Default value is true, 
                        // meaning that you also receive the packets you send to the multicast group. 
                        // To stop receiving these packets, you can set the property following to false
                         _client.MulticastLoopback = true;
    
                        // Set a flag indicating that we have now joined the multicast group 
                        _joined = true;
    
                        // Let others know we have joined by sending out a message to the group.
                        Send("Joined the group");
    
                        // Wait for data from the group. This is an asynchronous operation 
                        // and will not block the UI thread.
                        Receive();
                    }, null);
            }
    
    

    このメソッドはまず、定義されているグループ アドレスとポート値を使用して、UdpAnysourceMulticastClient クラスのインスタンスを作成します。この時点で、まだグループに参加していません。グループに参加するには、UdpAnysourceMulticastClient インスタンスで BeginJoinGroup メソッドを呼び出します。これは非同期の呼び出しです。上記のコードではインラインでコールバックが実装されていますが、それが優先されるスタイルであれば、独自のメソッドに移動することもできます。このコールバックで、参加を完了し、グループに参加したことを示すフラグを設定して、すぐに Send メソッドを使用して、グループにメッセージを送信します。さらに、Receive メソッドを呼び出して、グループでトラフィックのリッスンも開始します。Send メソッドと Receive メソッドは MainPage.xaml.cs に実装されており、次のセクションで説明します。

マルチキャスト グループにデータを送信するには

  • MainPage クラスに次のメソッドを追加します。

    
            /// <summary>
            /// Send the given message to the multicast group.
            /// </summary>
            /// <param name="message">The message to send</param>
            private void Send(string  message)
            {
                // Attempt the send only if you have already joined the group.
                if (_joined)
                {
                    byte[] data = Encoding.UTF8.GetBytes(message);
                    _client.BeginSendToGroup(data, 0, data.Length,
                        result =>
                        {
                            _client.EndSendToGroup(result);
    
                            // Log what we just sent
                            Log(message, true);
                            
                        }, null);
                }
                else
                {
                    Log("Message was not sent since you are not joined to the group", true);
                }
            }
    
    

    上記のメソッドでは、入力としてテキストの文字列を取得し、それをマルチキャスト グループに送信します。グループに参加していることを確認するために、まずチェックが行われます。UdpAnySourceMulticastClient.BeginSendToGroup 非同期メソッドを使用して、データがマルチキャスト グループに送信されます。このメソッドのコールバックは、インラインで実装されます。このコールバックは送信操作を完了し、アプリケーション UI に送信されたメッセージをログに記録してから、グループからのデータのリッスンを続行します。既定で、UdpAnysourceMulticastClientMulticastLoopback プロパティは true であり、これはグループに送信したメッセージを受信することを意味します。このプロパティが false に設定されている場合は、送信したメッセージを受信しません。

マルチキャスト グループからデータを受信するには

  • MainPage クラスに次のメソッドを追加します。

    
            /// <summary>
            /// Receive data from the group and log it.
            /// </summary>
            private void Receive()
            {
                // Only attempt to receive if you have already joined the group
                if (_joined)
                {
                    Array.Clear(_receiveBuffer, 0, _receiveBuffer.Length);
                    _client.BeginReceiveFromGroup(_receiveBuffer, 0, _receiveBuffer.Length,
                        result =>
                        {
                            IPEndPoint source;
    
                            // Complete the asynchronous operation. The source field will 
                            // contain the IP address of the device that sent the message
                            _client.EndReceiveFromGroup(result, out source);
    
                            // Get the received data from the buffer.
                            string dataReceived = Encoding.UTF8.GetString(_receiveBuffer, 0, _receiveBuffer.Length);
    
                            // Create a log entry.
                            string message = String.Format("[{0}]: {1}", source.Address.ToString(), dataReceived);
    
                            // Log it.
                            Log(message, false);
    
                            // Call receive again to continue to "listen" for the next message from the group
                            Receive();
                        }, null);
                }
                else
                {
                    Log("Cannot receive. You are currently not joined to the group", true);
                }
            }
    
    

    上記のメソッドでは、UdpAnySourceMulticastClient.BeginReceiveFromGroup 非同期メソッドを使用してマルチキャスト グループからデータを受信します。このメソッドのコールバックは、インラインで実装されます。このコールバックは受信操作を完了します。EndReceiveFromGroup で、ソース IP アドレスが out パラメーターとして返されることに注意してください。これは、このデータをグループに送信したグループ メンバーのアドレスを指定します。このソース アドレスの用途の 1 つは、ユニキャスト UdpAnySourceMulticastClient.BeginSendTo 非同期メソッドを使用して、このソースと直接通信することです。この例では、各メッセージのソースを示すため、単にアプリケーション UI にアドレスを記録します。

このセクションでは、このトピックで生成されたアプリケーションを実行する方法について説明します。

UDP マルチキャスト アプリケーションを実行するには

  1. デバイスまたはエミュレーターで、[デバッグ] メニューの [デバッグ開始] をクリックしてアプリケーションを実行します。

  2. アプリケーションが起動したら、マルチキャスト グループに参加したことを通知するテキストがメッセージ領域に表示されるはずです。

  3. アプリケーションが正常にマルチキャスト グループに参加したら、[Text To Send] とラベル付けされている入力テキスト フィールドにテキストを入力して、[Send] ボタンをクリックして、データをマルチキャスト グループに送信できます。

  4. 送信するメッセージは、発信メッセージ (>> 記号で示される) および着信メッセージ (<< 記号で示される) としてメッセージ領域に表示されるはずです。

  5. アプリケーションをエミュレーターで実行した後に、別のコンピューターの別のエミュレーターを使用するか、Wi-Fi で同じサブネットワークに接続されている他のデバイスを使用して、このアプリケーションをテストする必要があります。

このトピックでは、マルチキャスト グループを介した通信方法について説明します。上記のコードは、基本的な参加/送信/受信操作を実装しています。マルチキャスト アプリケーションを作成する場合は、次のことを考慮する必要があります。これはすべてを網羅したリストではありません。アプリケーションの製品化のための一部の考慮事項を示しています。

マルチキャスト アプリケーションを作成する場合のその他の考慮事項

  • エラー処理: UdpAnysourceMulticastClient での非同期メソッドの各呼び出しで例外が発生する可能性があります。ソケットのアクセスでエラーが発生した場合、SocketException 例外が発生します。これらの例外を適切に処理する必要があります。

  • 高速アプリケーション切り替え: アプリケーションが再アクティブ化されたら、BeginJoinGroup を再度呼び出して、マルチキャスト グループに再参加します。同じ UdpAnysourceMulticastClient オブジェクトを使用できます。

  • ユニキャストを使用した通信: この例では、マルチキャスト メッセージを送受信して、マルチキャスト グループでの通信方法を示しています。これは、ピアツーピア通信を実装する推奨される方法です。上記セクションで説明したように、受信した各メッセージのソース endPoint を使用して、指定したソースと直接通信できます。この機能の例は、ダウンロードで提供されています。詳細については、「マルチキャスト ソケットのサンプル」を参照してください。

表示: