How to set connection requirements for a socket for Windows Phone 8

[ This article is for Windows Phone 8 developers. If you’re developing for Windows 10, see the latest documentation. ]

In some applications, it is important to be able to restrict socket communication to a specific network interface type. Windows Phone enables applications to specify the type of network interface to use for network communication by using the SetNetworkRequirement socket extension method. This can be Cellular or NonCellular, meaning a network interface that uses cellular technology or a network interface that does not use cellular technology, respectively. Examples of NonCellular technology are Wi-Fi and Ethernet. The network requirements are set before a call to ConnectAsync is made. If an application’s network interface requirement can be satisfied, it is used for network communication. If the network interface requirements cannot be satisfied, a SocketError..::.NetworkDown error will be received in the ConnectAsync callback method and the socket will not be connected. This topic demonstrates how to set a network interface requirement on a socket and then verify the current interface if the socket is connected.

The Microsoft.Phone.Net.NetworkInformation namespace provides extension methods to the Socket class. You can use the SetNetworkPreference(Socket, NetworkSelectionCharacteristics) method to set the preference for a network interface on a socket.

Note

For more information about extension methods, see How to: Call an Extension Method (Visual Basic) or Extension Methods (C# Programming Guide).

Setting Connection Requirements for a Socket

In the following procedure, you put the code in a button click event for testing purposes only. The following procedure assumes that you have a Windows Phone application that has a page with a button named button1.

To set connection requirements for a socket

  1. At the top of the code-behind file for your page, add the following using directives.

    using System.Net.Sockets;
    using Microsoft.Phone.Net.NetworkInformation;
    using System.Text;
    
  2. Add the following variable declaration to the top of your class in the code-behind file. This defines the required network interface, which in this example is Cellular. If a connection cannot be established using a network interface of this type, the socket connection will fail.

    NetworkSelectionCharacteristics _requiredNetwork = NetworkSelectionCharacteristics.Cellular;
    
  3. Add the following code to your button click event. This creates a socket and calls the SetNetworkRequirement extension method on the socket to set the required network interface to use for the socket to the value of the _requiredNetwork variable defined previously. A connection is then initiated.

    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);
     }
    
Important Note:

For this example to work, you must change the serverName and the portNumber in the following code to refer to a service and its port that you can communicate with over this TCP socket. If this is not done, a time-out will be received for the connection request.

Tip

Instead of a server or host name in the DnsEndPoint constructor in the following code, you can use the string representation of an IP address. You can also use an IPEndPoint instead of a DnsEndPoint for the RemoteEndPoint property of the SocketAsyncEventArgs.

In the preceding method, we assigned the [Completed](https://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.completed\(v=VS.105\)) event handler to Connect\_Completed. This is the callback that is called when the asynchronous socket connection request completes or times out.
  1. In the same code-behind page, add the following method.

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

    In the preceding method, the success of the connection request is determined by looking at the SocketError property on the SocketAsyncEventArgs. If the connection was successful, a call is made to the ShowNetworkInterfaceInformation method, which will be described in the next step. The DisplayMessage method is also described in the following steps.

    If the network requirements cannot be fulfilled, a SocketError..::.NetworkDown error will be received in this callback and the socket will not be connected. This can happen, for example, if we are running this code in the emulator and we have set our requirements to Cellular.

  2. Add the following method. It retrieves the NetworkInterfaceInfo by calling the GetCurrentNetworkInterface on the connected socket. A StringBuilder is used to construct informational text containing network interface information. This text is displayed in a MessageBox to the user.

    /// <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();
    
    }
    
  3. In the same code-behind page, add the following method.

    /// <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);
       });
    }
    
  4. To build the solution, click Build Solution on the Build menu. (Ctrl+Shift+B). To run the application, click Start Debugging. (F5 on the Debug menu). If the socket communication can be established over the network interface type specified in the SetNetworkRequirement method, then the following message box is shown.

    If the socket communication cannot be established over the network interface type specified in the call to SetNetworkRequirement then a message box will be displayed informing you of that fact.

Note

In the preceding image, the value of Interface SubType is Unknown. However, when the phone is connected to a cellular network, instead of being tethered or connected over Wi-Fi, this field displays the cellular network type, such as 2G and 3G.

See Also

Reference

System.Net.Sockets

Microsoft.Phone.Net.NetworkInformation

NetworkSelectionCharacteristics

Other Resources

How to set connection preferences for a socket for Windows Phone 8

Sockets for Windows Phone 8

Network and network interface information for Windows Phone 8