정보
요청한 주제가 아래에 표시됩니다. 그러나 이 주제는 이 라이브러리에 포함되지 않습니다.

Windows Phone 8의 멀티캐스트 그룹에서 데이터를 보내고 받는 방법

2014-06-18

적용 대상: Windows Phone 8 및 Windows Phone Silverlight 8.1 | Windows Phone OS 7.1

 

이 항목에서는 멀티캐스트 그룹을 통한 통신 방법에 대해 설명합니다. 멀티캐스트 트래픽은 인터넷에서 확장 가능한 다대다 통신 방법입니다. 통신은 각각 멀티캐스트 그룹 주소라는 IP 주소로 식별되는 멀티캐스트 그룹 내에서 수행됩니다. 장치가 멀티캐스트 그룹 주소에 등록됩니다. 그러면 등록된 장치가 멀티캐스트 그룹으로 보내는 모든 패킷을 멀티캐스트 주소에 등록된 다른 모든 장치가 수신하게 됩니다. 이 항목에서는 System.Net.Sockets 네임스페이스에서 제공되는 UdpAnySourceMulticastClient 클래스를 사용하여 Windows Phone OS 7.1 의 멀티캐스트 그룹에 가입하기 위해 수행해야 하는 단계를 소개합니다. 이 기능을 설명하는 앱의 완성된 샘플을 다운로드할 수 있습니다. 자세한 내용은 멀티캐스트 소켓 샘플을 참조하세요.

이 항목에는 다음 단원이 포함되어 있습니다.

 

이 섹션에서는 UI를 만들어 UDP 멀티캐스트 기능을 설명합니다. 이 기능은 Windows Phone 앱입니다. 앱은 시작 시 멀티캐스트 그룹에 가입합니다. 그룹에 가입한 앱은 멀티캐스트 그룹으로 보낸 메시지를 받을 뿐만 아니라 멀티캐스트 그룹에 메시지를 보낼 수도 있습니다. UI에는 멀티캐스트 그룹으로 보낸 모든 데이터가 표시됩니다. 메시지를 입력해 멀티캐스트 그룹으로 보낼 수도 있습니다.

UI를 만들려면

  1. Visual Studio 에서 파일 | 새 프로젝트 메뉴 명령을 선택하여 새 프로젝트를 만듭니다.

  2. 새 프로젝트 창이 표시됩니다. Visual C# 템플릿을 확장한 다음 Windows Phone 템플릿을 선택합니다.

  3. Windows Phone 앱  템플릿을 선택합니다. 이름에 원하는 이름을 입력합니다.

  4. 확인을 클릭합니다. Windows Phone 플랫폼 선택 대화 상자가 나타납니다. 대상 버전을 선택하거나 기본 버전을 적용합니다.

  5. 확인을 클릭합니다. 새 프로젝트가 만들어지고 MainPage.xaml이 Visual Studio 디자이너 창에서 열립니다.

  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>
    
    
    

    위의 XAML 코드는 다음 스크린샷과 같은 간단한 사용자 인터페이스를 만듭니다.

    BasicUDPMulticastClient How To Screenshot

    다음 섹션에서는 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 웹 사이트를 참조하세요.

    • GROUP_PORT: 멀티캐스트 그룹과의 모든 통신을 수행하는 데 사용되는 포트 번호를 정의합니다. 이 예제에서도 임의의 값을 사용하므로 원하는 값을 선택해도 됩니다.

    • UdpAnySourceMulticastClient: Windows Phone OS 7.1 에서 제공되는 이 클래스는 UDP를 통해 멀티캐스트 그룹과 통신하는 데 필요한 논리를 캡슐화합니다. 이 예제에서는 이 클래스의 인스턴스를 만들어 Join, SendReceive 메서드에서 사용합니다. 단일 원본에서 멀티캐스트 트래픽을 받는 방법에 대한 자세한 내용은 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 메서드를 호출하여 그룹에 대한 트래픽 "수신 대기"도 시작합니다. MainPage.xaml.cs에서 구현되는 SendReceive 메서드는 다음 섹션에서 설명합니다.

멀티캐스트 그룹으로 데이터를 보내려면

  • 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);
                }
            }
    
    

    위의 메서드는 텍스트 문자열을 입력으로 가져와 멀티캐스트 그룹으로 보냅니다. 이때 그룹에 가입되었는지를 먼저 확인합니다. 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);
                }
            }
    
    

    위의 메서드에서는 BeginReceiveFromGroup 비동기 메서드를 사용하여 멀티캐스트 그룹에서 데이터를 받습니다. 이 메서드에 대한 콜백은 인라인으로 구현됩니다. 이 콜백을 사용하여 수신 작업을 완료합니다. EndReceiveFromGroup에서 원본 IP 주소는 out 매개 변수로 반환됩니다. 이 매개 변수는 해당 데이터를 그룹으로 보낸 그룹 멤버의 주소를 지정합니다. 이 원본 주소를 사용하는 방법 중 하나는, 유니캐스트 BeginSendTo 비동기 메서드를 사용해 이 원본과 직접 다시 통신하는 것입니다. 이 예제에서는 각 메시지의 원본을 표시하기 위해 앱 UI에 주소만 기록합니다.

이 섹션에서는 이 항목에서 생성한 앱을 실행하는 방법을 설명합니다.

UDP 멀티캐스트 앱을 실행하려면

  1. 장치 또는 에뮬레이터에서, 디버그 | 디버깅 시작 메뉴 명령을 선택하여 앱을 실행합니다.

  2. 앱이 시작되면 멀티캐스트 그룹에 가입되었음을 알리는 텍스트가 메시지 영역에 표시됩니다.

  3. 앱이 멀티캐스트 그룹에 가입된 경우 레이블이 보낼 텍스트인 입력 텍스트 필드에 텍스트를 입력하고 보내기 버튼을 클릭하여 데이터를 멀티캐스트 그룹으로 보낼 수 있습니다.

  4. 보내는 데이터는 메시지 영역에도 >> 기호로 표시되는 발신 메시지와, << 기호로 표시되는 수신 메시지로 나타나야 합니다.

  5. 에뮬레이터에서 앱 작동이 완료된 후에는 다른 컴퓨터의 다른 에뮬레이터 또는 동일한 하위 네트워크에 Wi-Fi로 연결된 다른 장치를 사용하여 이 앱을 테스트해야 합니다.

이 항목에서는 멀티캐스트 그룹을 통한 통신 방법에 대해 설명합니다. 위의 코드는 기본 가입/보내기/받기 작업을 구현합니다. 멀티캐스트 앱을 만들 때는 다음 사항을 고려해야 합니다. 이 목록에는 전체 고려 사항이 포함되어 있지는 않습니다. 여기에서는 앱 생성 시 고려할 사항을 중점적으로 제시합니다.

멀티캐스트 앱을 만들 때 고려해야 할 기타 사항

  • 오류 처리: UdpAnySourceMulticastClient에서 비동기 메서드를 호출할 때마다 예외가 발생할 수 있습니다. 소켓 액세스 오류 시에는 SocketException 예외가 발생합니다. 이러한 예외를 적절하게 처리해야 합니다.

  • 빠른 응용프로그램 전환: 앱이 다시 활성화되면 BeginJoinGroup을 다시 호출하여 멀티캐스트 그룹에 다시 가입합니다. 이때 동일한 UdpAnySourceMulticastClient 개체를 사용할 수 있습니다.

  • 유니캐스트를 사용한 통신: 이 예제에서는 멀티캐스트 메시지를 보내고 받는 방식으로 멀티캐스트 그룹에서 통신하는 방법을 보여 줍니다. 피어 투 피어 통신을 구현할 때는 이 방식을 사용하는 것이 좋습니다. 위 섹션에서 설명한 것처럼, 수신된 각 메시지의 원본 endPoint를 사용하여 지정된 원본과 직접 통신할 수 있습니다. 이 기능의 예제는 다운로드할 수 있습니다. 자세한 내용은 멀티캐스트 소켓 샘플을 참조하세요.

표시: