방법: Windows Phone의 소켓에 대한 연결 요구 사항 설정

2012-02-09

일부 응용프로그램에서는 소켓 통신을 특정 네트워크 인터페이스 유형으로 제한하는 기능이 중요합니다. Windows Phone OS 7.1 에서는 응용프로그램이 SetNetworkRequirement 소켓 확장 메서드를 사용하여 네트워크 통신에 사용할 네트워크 인터페이스 유형을 지정할 수 있습니다. 유형은 Cellular 또는 NonCellular일 수 있으며 각각 셀룰러 기술을 사용하는 네트워크 인터페이스 또는 셀룰러 기술을 사용하지 않는 네트워크 인터페이스를 의미합니다. NonCellular 기술의 예로 Wi-Fi와 이더넷이 있습니다. 네트워크 요구 사항은 ConnectAsync 호출 전에 설정됩니다. 응용프로그램의 네트워크 인터페이스 요구 사항을 충족할 수 있는 경우 네트워크 통신에 사용됩니다. 네트워크 인터페이스 요구 사항을 충족할 수 없는 경우 ConnectAsync 콜백 메서드에서 SocketError.NetworkDown 오류가 수신되며 소켓이 연결되지 않습니다. 이 항목에서는 소켓에서 네트워크 인터페이스 요구 사항을 지정한 다음 소켓이 연결되면 현재 인터페이스를 확인하는 방법을 보여 줍니다.

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

참고참고:

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

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

소켓의 연결 요구 사항을 설정하려면

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

    
    using System.Net.Sockets;
    using Microsoft.Phone.Net.NetworkInformation;
    using System.Text;
    
    
  2. 코드 숨김 파일에서 클래스의 맨 위에 다음 변수 선언을 추가합니다. 이 선언은 필요한 네트워크 인터페이스(이 예제에서는 Cellular)를 정의합니다. 이 유형의 네트워크 인터페이스를 사용하여 연결할 수 없는 경우 소켓 연결이 실패합니다.

    
    NetworkSelectionCharacteristics _requiredNetwork = NetworkSelectionCharacteristics.Cellular;
    
    
  3. 버튼 클릭 이벤트에 다음 코드를 추가합니다. 이 코드는 소켓을 만들고 소켓에서 SetNetworkRequirement 확장 메서드를 호출하여 소켓에 사용할 필수 네트워크 인터페이스를 앞에서 정의한 _requiredNetwork 변수의 값으로 설정합니다. 그런 다음 연결을 시작합니다.

    
    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.SetNetworkRequirement(_requiredNetwork);
    
       // 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 += new EventHandler<SocketAsyncEventArgs>(Connect_Completed);
    
       // Make an asynchronous Connect request over the socket.
       socket.ConnectAsync(socketEventArg);
     }
    
    
    중요중요:

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

    팁팁:

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

    앞의 메서드에서 Connect_Completed에 Completed 이벤트 처리기를 할당했습니다. 이것은 비동기 소켓 연결 요청이 완료되거나 시간 초과될 때 호출되는 콜백입니다.

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

    
    void Connect_Completed(object sender, SocketAsyncEventArgs e)
    {
       switch (e.SocketError)
       {
          case SocketError.NetworkDown:
             DisplayMessage(String.Format("Could not connect over the required network interface '{0}'", _requiredNetwork.ToString()),"Error",MessageBoxButton.OK);
          break;
          case SocketError.Success:
             ShowNetworkInterfaceInformation(e);
             break;
         default:
            DisplayMessage(String.Format("Socket Connection Failed with the error: '{0}'", e.SocketError.ToString()),"Error",MessageBoxButton.OK);
            break;
       }
     }
    
    
    

    앞의 메서드에서 연결 요청의 성공은 SocketAsyncEventArgsSocketError 속성을 보고 확인합니다. 연결에 성공한 경우 다음 단계에서 설명하는 ShowNetworkInterfaceInformation 메서드가 호출됩니다. DisplayMessage 메서드도 다음 단계에서 설명합니다.

    네트워크 요구 사항을 충족할 수 없는 경우 이 콜백에서 SocketError.NetworkDown 오류가 수신되며 소켓이 연결되지 않습니다. 예를 들어 에뮬레이터에서 이 코드를 실행 중이며 요구 사항을 Cellular로 설정한 경우 이 오류가 발생할 수 있습니다.

  5. 다음 메서드를 추가합니다. 이 메서드는 연결 소켓에서 GetCurrentNetworkInterface를 호출하여 NetworkInterfaceInfo를 검색합니다. StringBuilder는 네트워크 인터페이스 정보가 포함된 정보 텍스트를 생성하는 데 사용됩니다. 이 텍스트는 MessageBox에서 사용자에게 표시됩니다.

    
    /// <summary>
    /// Display the network information using the GetCurrentNetworkInterface extension method on the socket.
    /// </summary>
    void ShowNetworkInterfaceInformation(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 create 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. 
       socket.Close();
        
    }
    
    
  6. 동일한 코드 숨김 페이지에서 다음 메서드를 추가합니다.

    
    /// <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);
       });
    }
    
    
  7. 솔루션을 빌드하려면 빌드 메뉴에서 솔루션 빌드를 클릭합니다. (Ctrl+Shift+B). 응용프로그램을 실행하려면 디버깅 시작을 클릭합니다. (디버그 메뉴의 F5). SetNetworkRequirement 메서드에 지정된 네트워크 인터페이스 유형을 통해 소켓 통신을 설정할 수 없는 경우 다음 메시지 상자가 표시됩니다.

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

    SetNetworkRequirement 호출에 지정된 네트워크 인터페이스 유형을 통해 소켓 통신을 설정할 수 없는 경우 해당 사실을 알리는 메시지 상자가 표시됩니다.

    참고참고:

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

표시: