MSDN Library

如何在 Windows Phone 中为套接字设置连接首选项

2012/2/9

通过 Windows Phone OS 7.1,应用程序可以设置网络接口类型的首选项以用于网络通信。这可能是手机网络非手机网络,分别指使用手机网络技术的网络接口或不使用手机网络技术的网络接口。非手机网络技术的示例为 WLAN 和以太网。如果满足了应用程序的首选项,则其会被用于网络通信。如果不满足,则使用其他网络接口进行网络通信(如果可用)。本主题演示如何在套接字上设置网络接口首选项,然后在连接该套接字后,验证当前接口。

Microsoft.Phone.Net.NetworkInformation 命名空间向套接字类提供扩展方法。您可以使用 SetNetworkPreference(Socket, NetworkSelectionCharacteristics) 方法在套接字上设置网络接口的首选项。

注意注意:

有关扩展方法的更多信息,请参阅如何调用扩展方法 (Visual Basic)扩展方法(C# 编程指南)

在下面的步骤中,您可以仅出于测试目的将代码置于一个按键的点按事件中。下面的过程假定 Windows Phone 应用程序具有一个包含名为 button1 按键的页面。

为套接字设置连接首选项

  1. 在您页面的代码隐藏文件顶部,添加以下语句。

    
    using System.Net.Sockets;
    using Microsoft.Phone.Net.NetworkInformation;
    using System.Text;
    
    
  2. 将以下代码添加到您的按键点击事件中。这会创建一个套接字,并调用套接字上的 SetNetworkPreference 扩展方法,将用于该套接字的首选网络接口设置为手机网络。然后启动连接。虽然可以在未连接的套接字上调用 SetNetworkPreference,但在此,我们首先尝试进行连接,以便能够检索当前网络接口信息。套接字上当前网络接口的检索操作通过 GetCurrentNetworkInterface(Socket) 扩展方法来完成,并将显示在本过程的下一步骤中。

    重要说明重要说明:

    为了使此示例能够正常运行,必须在以下代码中将 serverNameportNumber 更改为引用可通过此 TCP 套接字与其进行通信的服务及其端口。如果未执行此操作,连接请求会收到超时。

    提示提示:

    您可以使用代表 IP 地址的字符串,而不使用下面的代码中 DnsEndPoint 构造函数中的服务器或主机名。您还可以使用 IPEndpoint,而不使用 SocketAsyncEventArgs 的 RemoteEndPoint 属性的 DnsEndPoint。

    
            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。这是在异步套接字连接请求完成或超时时调用的回调。如果连接成功,我们会在该方法中获取该套接字的所有网络接口信息。在此示例中,我们会使用此信息显示该套接字实际上采用了的网络接口,这样就可以在对 SetNetworkPreference 的调用中与前面代码中的首先项设置进行比较。

    注意注意:

    如果您的应用程序需要特定的网络接口技术,则可以使用扩展方法 SetNetworkRequirement(Socket, NetworkSelectionCharacteristics) 定义所需的手机网络非手机网络接口。

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

    在前面的方法中,通过查看 SocketAsyncEventArgs 上的 SocketError 属性来确定连接请求是否成功。如果连接成功,则会对套接字对象上的 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

    “如何获取连接信息”的屏幕截图
    注意注意:

    在前面的图像中,“Interface SubType”的值为“未知”。但是,当连接到手机网络时,此字段不是通过 WLAN 叠接或连接,而是显示手机网络类型(例如 2G 和 3G)。

显示:
© 2016 Microsoft