방법: Windows Phone의 소켓에 대한 연결 기본 설정 지정

2012-02-09

Windows Phone OS 7.1 을 사용하면 응용프로그램이 네트워크 통신에 사용할 네트워크 인터페이스 유형의 기본 설정을 지정할 수 있습니다. 유형은 Cellular 또는 NonCellular일 수 있으며 각각 셀룰러 기술을 사용하는 네트워크 인터페이스 또는 셀룰러 기술을 사용하지 않는 네트워크 인터페이스를 의미합니다. NonCellular 기술의 예로 Wi-Fi와 이더넷이 있습니다. 응용프로그램의 기본 설정을 충족할 수 있는 경우 이 설정이 네트워크 통신에 사용됩니다. 충족할 수 없으면 네트워크 통신이 다른 네트워크 인터페이스(사용 가능한 경우)를 사용하여 수행됩니다. 이 항목에서는 소켓에서 네트워크 인터페이스 기본 설정을 지정한 다음 소켓이 연결되면 현재 인터페이스를 확인하는 방법을 보여 줍니다.

Microsoft.Phone.Net.NetworkInformation 네임스페이스는 Socket 클래스에 확장 메서드를 제공합니다. SetNetworkPreference(Socket, NetworkSelectionCharacteristics) 메서드를 사용하여 소켓에서 네트워크 인터페이스 기본 설정을 지정할 수 있습니다.

참고참고:

확장 메서드에 대한 자세한 내용은 방법: 확장 메서드 호출(Visual Basic) 또는 확장 메서드(C# 프로그래밍 가이드)를 참조하십시오.

다음 절차에서는 테스트 용도로만 버튼 클릭 이벤트에 코드를 넣습니다. 다음 절차에서는 button1이라는 버튼이 포함된 페이지가 있는 Windows Phone 응용프로그램을 사용한다고 가정합니다.

소켓의 연결 기본 설정을 지정하려면

  1. 페이지에 대한 코드 숨김 파일의 맨 위에 다음 문을 추가합니다.

    
    using System.Net.Sockets;
    using Microsoft.Phone.Net.NetworkInformation;
    using System.Text;
    
    
  2. 버튼 클릭 이벤트에 다음 코드를 추가합니다. 이 코드는 소켓을 만들고 소켓에서 SetNetworkPreference 확장 메서드를 호출하여 소켓에 사용할 기본 네트워크 인터페이스를 Cellular로 설정합니다. 그런 다음 연결을 시작합니다. 연결되지 않은 소켓에서 SetNetworkPreference를 호출할 수도 있지만 현재 네트워크 인터페이스 정보를 검색할 수 있도록 여기서 연결을 시도합니다. 소켓에서 현재 네트워크 인터페이스를 검색하는 작업은 GetCurrentNetworkInterface(Socket) 확장 메서드를 사용하여 수행되며 이 절차의 다음 단계에 나와 있습니다.

    중요중요:

    이 예제가 작동하려면 다음 코드의 serverNameportNumber가 이 TCP 소켓을 통해 통신할 수 있는 서비스와 해당 포트를 가리키도록 변경해야 합니다. 이 작업을 하지 않으면 연결 요청에 대해 시간 초과가 수신됩니다.

    팁팁:

    다음 코드의 DnsEndPoint 생성자에서 서버 또는 호스트 이름 대신 IP 주소의 문자열 표현을 사용할 수 있습니다. SocketAsyncEventArgs의 RemoteEndPoint 속성에 대해 DnsEndPoint 대신 IPEndpoint를 사용할 수도 있습니다.

    
            private void button1_Click(object sender, RoutedEventArgs e)
            {
    
                Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    
                // Set the preferred network interface to be an interface that uses cellular technology. 
                socket.SetNetworkPreference(NetworkSelectionCharacteristics.Cellular);
                
    
                // To run this application, you should specify the name of a server on your network that is running
                // the required service. Replace the following "Placeholder" text with the name of the server.
                string serverName = "Placeholder";
    
                // This identifies the port over which to communicate. In this sample, we need to just
                // supply the Echo port number, but you are free to select your own.
                int portNumber = 7;
    
                // Create DnsEndPoint. 
                DnsEndPoint hostEntry = new DnsEndPoint(serverName, portNumber);
    
                // Create a SocketAsyncEventArgs object to be used in the connection request.
                SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
                socketEventArg.RemoteEndPoint = hostEntry;
                socketEventArg.UserToken = socket;
                socketEventArg.Completed += ShowNetworkInterfaceInformation;
    
                // // Make an asynchronous Connect request over the socket.
                socket.ConnectAsync(socketEventArg);
            }
    
    

    앞의 메서드에서 ShowNetworkInterfaceInformation에 Completed 이벤트 처리기를 할당합니다. 이것은 비동기 소켓 연결 요청이 완료되거나 시간 초과될 때 호출되는 콜백입니다. 연결에 성공한 경우 이 메서드에서 소켓에 대한 모든 네트워크 인터페이스 정보를 가져옵니다. 이 예제에서는 이 정보를 사용하여 소켓이 실제로 사용 중인 네트워크 인터페이스를 표시합니다. 앞의 코드에서 SetNetworkPreference 호출에 설정된 기본 설정과 이 정보를 비교할 수 있습니다.

    참고참고:

    응용프로그램에 특정 네트워크 인터페이스 기술이 필요한 경우 확장 메서드 SetNetworkRequirement(Socket, NetworkSelectionCharacteristics)를 사용하여 필요한 Cellular 또는 NonCellular 네트워크 인터페이스를 정의할 수 있습니다.

  3. 동일한 코드 숨김 페이지에서 다음 메서드를 추가합니다.

    
            /// <summary>
            /// Display the network information using the GetCurrentNetworkInterface extension method on the socket.
            /// </summary>
            /// <remarks>This is the callback from the ConnectAsync method.</remarks>
            void ShowNetworkInterfaceInformation(object s, SocketAsyncEventArgs e)
            {
                // When ConnectAsync was called, it was passed the socket object in
                // the UserToken field of the socketEventArg. This context is retrieved once
                // the ConnectAsync has completed.
                Socket socket = e.UserToken as Socket;
    
                // Call GetCurrentNetworkInterface only if the connection was successful.
                if (e.SocketError == SocketError.Success)
                {
                    NetworkInterfaceInfo netInterfaceInfo = socket.GetCurrentNetworkInterface();
    
                    // Use a StringBuilder to efficiently build up an information text about this
                    // NetworkInterfaceInfo.
                    StringBuilder sb = new StringBuilder();
    
                    // For clarity, append a timestamp so that we can see when this information was gathered.
                    sb.AppendLine("Last Updated: " + DateTime.Now.ToString());
    
                    sb.Append("Interface Name: ");
                    sb.AppendLine(netInterfaceInfo.InterfaceName);
    
                    sb.Append("Interface State: ");
                    sb.AppendLine(netInterfaceInfo.InterfaceState.ToString());
    
                    sb.Append("Interface Type: ");
                    sb.AppendLine(netInterfaceInfo.InterfaceType.ToString());
    
                    sb.Append("Interface SubType: ");
                    sb.AppendLine(netInterfaceInfo.InterfaceSubtype.ToString());
    
                    DisplayMessage(sb.ToString(), "Network Interface Information", MessageBoxButton.OK);
                }
                else
                {
                    DisplayMessage(e.SocketError.ToString(), "Error Getting Interface Information", MessageBoxButton.OK);
                }
    
                // Close our socket since we no longer need it. 
                // The scope of this socket instance is this method. It is created every time the method is called. 
                // This was done purely to keep this method as self-contained as possible for this sample. 
                socket.Close();
            }
    
    

    앞의 메서드에서 연결 요청의 성공은 SocketAsyncEventArgsSocketError 속성을 보고 확인합니다. 연결에 성공한 경우 소켓 개체의 GetCurrentNetworkInterface 확장 메서드가 호출됩니다. NetworkInterfaceInfo 개체의 다양한 속성 값을 결합하여 단순 텍스트 출력이 생성됩니다. 최종적으로, 다음 코드에서 설명하는 DisplayMessage를 호출합니다.

  4. 동일한 코드 숨김 페이지에서 다음 메서드를 추가합니다.

    
            /// <summary>
            /// This helper method ensures that MessageBox.Show() is called on the UI thread.
            /// </summary>
            void DisplayMessage(string text, string caption, MessageBoxButton buttonConfiguration)
            {
                Dispatcher.BeginInvoke(() =>
                {
                    MessageBox.Show(text, caption, buttonConfiguration);
                });
            }
    
    
  5. 솔루션을 빌드하고 실행한 후 다음과 같은 MessageBox가 표시됩니다.

    방법: 연결 정보 가져오기 스크린샷
    참고참고:

    앞의 이미지에서 인터페이스 하위 유형의 값은 알 수 없음입니다. 하지만 Wi-Fi를 통해 테더링되거나 연결되는 대신 셀룰러 네트워크에 연결된 경우에는 이 필드에 2G, 3G 등의 셀룰러 네트워크 유형이 표시됩니다.

표시: