2012-07-18 111 views
3

我已經觀看了幾天有關Windows Phone 7的各種論壇,但沒有給我一個明確的答案。 到目前爲止,我還沒有能夠接收從通過WiFi連接到Windows Phone 7設備(在仿真器上運行)上連接的計算機發送的UDP數據包(不是廣播,也不是單播)。Windows Phone 7通過wifi接收UDP數據包(廣播或單播)

顯然應該支持UDP單播,下面的代碼可以正常運行,但是手機沒有收到UDP數據包。 我希望有人能糾正下面的代碼。

注意下面的代碼如下所有建議,目前給出的其他論壇,分別是:

  1. 首先發送一個數據包到目的地,然後聽答覆
  2. 不要使用廣播,但UDP單播(我能夠同時測試設置isBroadcast變量),其受Silverlight

MainPage.xaml中

允許
  • 使用端口個
    <phone:PhoneApplicationPage 
         x:Class="UDPClient.MainPage" 
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
         xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" 
         xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768" 
         FontFamily="{StaticResource PhoneFontFamilyNormal}" 
         FontSize="{StaticResource PhoneFontSizeNormal}" 
         Foreground="{StaticResource PhoneForegroundBrush}" 
         SupportedOrientations="Portrait" Orientation="Portrait" 
         shell:SystemTray.IsVisible="True"> 
    
         <!--LayoutRoot is the root grid where all page content is placed--> 
         <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="UDP Socket Application" Style="{StaticResource PhoneTextNormalStyle}"/> 
          <TextBlock x:Name="PageTitle" Text="Client" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> 
          </StackPanel> 
    
    
          <!--ContentPanel - place additional content here--> 
          <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,-8,12,8"> 
          <Grid.ColumnDefinitions> 
           <ColumnDefinition Width="Auto"/> 
           <!-- Fit to content --> 
           <ColumnDefinition Width="Auto"/> 
           <!-- Fit to content --> 
           <ColumnDefinition Width="Auto"/> 
           <!-- Fit to content --> 
           <ColumnDefinition Width="*"/> 
           <!-- Take up remaining space --> 
          </Grid.ColumnDefinitions> 
          <Grid.RowDefinitions> 
           <RowDefinition Height="Auto"/> 
           <!-- Fit to content --> 
           <RowDefinition Height="Auto"/> 
           <!-- Fit to content --> 
           <RowDefinition Height="Auto"/> 
           <!-- Fit to content --> 
           <RowDefinition Height="*"/> 
           <!-- Take up remaining space --> 
          </Grid.RowDefinitions> 
    
          <!-- Grid Row 0: Remote Host Input Field >--> 
          <TextBlock Grid.Row="0" Grid.Column="0" Text="Host Name:" 
           VerticalAlignment="Center" HorizontalAlignment="Center" 
           FontSize="{StaticResource PhoneFontSizeNormal}" /> 
          <TextBox x:Name="txtRemoteHost" Grid.Row="0" Grid.Column="1" Height="70" Width="200" 
           VerticalAlignment="Top" HorizontalAlignment="Left" 
           FontSize="{StaticResource PhoneFontSizeNormal}" Text="192.168.1.3" /> 
    
          <!-- Grid Row 1: Echo >--> 
          <!-- TextBlock for Echo command label--> 
          <TextBlock Grid.Row="1" Grid.Column="0" Text="Text To Echo:" 
           VerticalAlignment="Center" HorizontalAlignment="Center" 
           FontSize="{StaticResource PhoneFontSizeNormal}" /> 
    
          <!-- TextBox for Echo command text input--> 
          <TextBox x:Name="txtInput" Grid.Row="1" Grid.Column="1" Height="70" Width="200" 
           VerticalAlignment="Top" HorizontalAlignment="Left" 
           FontSize="{StaticResource PhoneFontSizeNormal}" Text="test..." /> 
    
          <!-- Button to the right of the input textbox for the Echo command >--> 
          <Button x:Name="btnEcho" Grid.Row="1" Grid.Column="2" Height="70" Width="120" 
           Content="Echo" 
           FontSize="{StaticResource PhoneFontSizeNormal}" Click="btnEcho_Click"/> 
    
          <!-- Grid Row 2: Quote of the Day--> 
          <!-- Button for the Quote command >--> 
          <Button x:Name="btnGetQuote" Grid.Row="2" Grid.ColumnSpan="4" Height="70" 
           Content="Get Quote of the Day" 
           FontSize="{StaticResource PhoneFontSizeNormal}" Click="btnGetQuote_Click"/> 
          <!-- Grid Row 3: Output--> 
          <!-- Output TextBox named 'txtOutput' >--> 
          <TextBox x:Name="txtOutput" Grid.Row="3" Grid.ColumnSpan="4" Background="Black" BorderBrush="Green" 
           AcceptsReturn="False" Foreground="LightGray" FontFamily="Courier New" 
           IsHitTestVisible="False" FontSize="{StaticResource PhoneFontSizeSmall}" TextWrapping="Wrap" /> 
          <Button Content="Listen" Grid.Column="1" Grid.ColumnSpan="2" Height="70" HorizontalAlignment="Left" Margin="195,0,0,0" Name="Listenbutton" VerticalAlignment="Top" Width="125" Click="Listenbutton_Click" /> 
          </Grid> 
         </Grid> 
    
         <!--Sample code showing usage of ApplicationBar--> 
         <!--<phone:PhoneApplicationPage.ApplicationBar> 
          <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True"> 
          <shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/> 
          <shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/> 
          <shell:ApplicationBar.MenuItems> 
           <shell:ApplicationBarMenuItem Text="MenuItem 1"/> 
           <shell:ApplicationBarMenuItem Text="MenuItem 2"/> 
          </shell:ApplicationBar.MenuItems> 
          </shell:ApplicationBar> 
         </phone:PhoneApplicationPage.ApplicationBar>--> 
    
         </phone:PhoneApplicationPage> 
    

    MainPage.xaml.cs中

    using System; 
        using System.Collections.Generic; 
        using System.Linq; 
        using System.Net; 
        using System.Windows; 
        using System.Windows.Controls; 
        using System.Windows.Documents; 
        using System.Windows.Input; 
        using System.Windows.Media; 
        using System.Windows.Media.Animation; 
        using System.Windows.Shapes; 
        using Microsoft.Phone.Controls; 
        using System.Net.Sockets; 
        using System.Threading; 
    
    
        namespace UDPClient 
        { 
        public partial class MainPage : PhoneApplicationPage 
        { 
        // Constructor 
        public MainPage() 
        { 
        InitializeComponent(); 
        } 
    
        // Constants 
        const int ECHO_PORT = 7; // The Echo protocol uses port 7 in this sample 
        const int QOTD_PORT = 17; // The Quote of the Day (QOTD) protocol uses port 17 in this sample 
        const int UDP_PORT = 4502; 
        /// <summary> 
        /// Handle the btnEcho_Click event by sending text to the echo server and outputting the response 
        /// </summary> 
        private void btnEcho_Click(object sender, RoutedEventArgs e) 
        { 
        // Clear the log 
        ClearLog(); 
    
        // Make sure we can perform this action with valid data 
        if (ValidateRemoteHost() && ValidateInput()) 
        { 
         // Instantiate the SocketClient 
         SocketClient client = new SocketClient(); 
         SocketAsyncEventArgs socketEventArg; 
    
         // Attempt to send our message to be echoed to the echo server 
         Log(String.Format("Sending '{0}' to server ...", txtInput.Text), true); 
         string result = client.Send(txtRemoteHost.Text, ECHO_PORT, txtInput.Text, false, out socketEventArg); 
         Log(result, false); 
    
         // Receive a response from the echo server 
         Log("Requesting Receive ...", true); 
         result = client.UDPReceive(ECHO_PORT, false); 
         Log(result, false); 
    
         // Close the socket connection explicitly 
         client.Close(); 
        } 
    
        } 
    
        private void Listenbutton_Click(object sender, RoutedEventArgs e) 
        { 
        // Clear the log 
        ClearLog(); 
    
        // Make sure we can perform this action with valid data 
        if (ValidateRemoteHost()) 
        { 
         // Instantiate the SocketClient 
         SocketClient client = new SocketClient(); 
    
         // Receive packets 
         string result = client.UDPReceive(UDP_PORT, false); 
         Log(result, false); 
         // Close the socket connection explicitly 
         client.Close(); 
        } 
        } 
    
        /// <summary> 
        /// Handle the btnGetQuote_Click event by receiving text from the Quote of the Day (QOTD) server and outputting the response 
        /// </summary> 
        private void btnGetQuote_Click(object sender, RoutedEventArgs e) 
        { 
        // Clear the log 
        ClearLog(); 
        // Receive response from the QOTD server 
        Log("nothing...", true);; 
        } 
        } 
    
        #region UI Validation 
        /// <summary> 
        /// Validates the txtInput TextBox 
        /// </summary> 
        /// <returns>True if the txtInput TextBox contains valid data, False otherwise</returns> 
        private bool ValidateInput() 
        { 
        // txtInput must contain some text 
        if (String.IsNullOrWhiteSpace(txtInput.Text)) 
        { 
         MessageBox.Show("Please enter some text to echo"); 
         return false; 
        } 
    
        return true; 
        } 
    
        /// <summary> 
        /// Validates the txtRemoteHost TextBox 
        /// </summary> 
        /// <returns>True if the txtRemoteHost contains valid data, False otherwise</returns> 
        private bool ValidateRemoteHost() 
        { 
        // The txtRemoteHost must contain some text 
        if (String.IsNullOrWhiteSpace(txtRemoteHost.Text)) 
        { 
         MessageBox.Show("Please enter a host name"); 
         return false; 
        } 
    
        return true; 
        } 
        #endregion 
    
        #region Logging 
        /// <summary> 
        /// Log text to the txtOutput TextBox 
        /// </summary> 
        /// <param name="message">The message to write to the txtOutput TextBox</param> 
        /// <param name="isOutgoing">True if the message is an outgoing (client to server) message, False otherwise</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) 
        { 
        string direction = (isOutgoing) ? ">> " : "<< "; 
        txtOutput.Text += Environment.NewLine + direction + message; 
        } 
    
        /// <summary> 
        /// Clears the txtOutput TextBox 
        /// </summary> 
        private void ClearLog() 
        { 
        txtOutput.Text = String.Empty; 
        } 
        #endregion 
    } 
    } 
    

    SocketClient.cs

    using System; 
        using System.Net; 
        using System.Windows; 
        using System.Windows.Controls; 
        using System.Windows.Documents; 
        using System.Windows.Ink; 
        using System.Windows.Input; 
        using System.Windows.Media; 
        using System.Windows.Media.Animation; 
        using System.Windows.Shapes; 
        using System.Net.Sockets; 
        using System.Threading; 
        using System.Text; 
    
        namespace UDPClient 
        { 
        public class SocketClient 
        { 
        // Cached Socket object that will be used by each call for the lifetime of this class 
        Socket _socket = null; 
        // Signaling object used to notify when an asynchronous operation is completed 
        static ManualResetEvent _clientDone = new ManualResetEvent(false); 
        // Define a timeout in milliseconds for each asynchronous call. If a response is not received within this 
        // timeout period, the call is aborted. 
        const int TIMEOUT_MILLISECONDS = 1000; 
        // The maximum size of the data buffer to use with the asynchronous socket methods 
        const int MAX_BUFFER_SIZE = 2048; 
        bool isHasSent = false; 
        int errorCode = 0; 
    
        /// <summary> 
        /// SocketClient Constructor 
        /// </summary> 
        public SocketClient() 
        { 
        // The following creates a socket with the following properties: 
        // AddressFamily.InterNetwork - the socket will use the IP version 4 addressing scheme to resolve an address 
        // SocketType.Dgram - a socket that supports datagram (message) packets 
        // PrototcolType.Udp - the User Datagram Protocol (UDP) 
        _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); 
        } 
    
        /// <summary> 
        /// Send the given data to the server using the established connection 
        /// </summary> 
        /// <param name="serverName">The name of the server</param> 
        /// <param name="portNumber">The number of the port over which to send the data</param> 
        /// <param name="data">The data to send to the server</param> 
        /// <returns>The result of the Send request</returns> 
        public string Send(string serverName, int portNumber, string data, bool isBroadcast, out SocketAsyncEventArgs socketEventArg) 
        { 
        string response = "Operation Timeout"; 
        // Create SocketAsyncEventArgs context object 
    
        // We are re-using the _socket object that was initialized in the Connect method 
        if (_socket != null) 
        { 
         socketEventArg = new SocketAsyncEventArgs(); 
         // Set properties on context object 
    
         System.Diagnostics.Debug.WriteLine("Send(): setting remoteEndPoint"); 
         if (isBroadcast) 
         socketEventArg.RemoteEndPoint = new IPEndPoint(IPAddress.Broadcast, portNumber); 
         else 
         socketEventArg.RemoteEndPoint = new DnsEndPoint(serverName, portNumber); 
         System.Diagnostics.Debug.WriteLine("Send(): remoteEndPoint correctly set"); 
    
         // Inline event handler for the Completed event. 
         // Note: This event handler was implemented inline in order to make this method self-contained. 
         socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) 
         { 
         response = e.SocketError.ToString(); 
         // Unblock the UI thread 
         _clientDone.Set(); 
    
         isHasSent = true; 
         }); 
    
         // Add the data to be sent into the buffer 
         byte[] payload = Encoding.UTF8.GetBytes(data); 
         socketEventArg.SetBuffer(payload, 0, payload.Length); 
    
         // Sets the state of the event to nonsignaled, causing threads to block 
         _clientDone.Reset(); 
    
         // Make an asynchronous Send request over the socket 
         _socket.SendToAsync(socketEventArg); 
    
         // Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds. 
         // If no response comes back within this time then proceed 
         _clientDone.WaitOne(TIMEOUT_MILLISECONDS); 
        } 
        else 
        { 
         socketEventArg = null; 
         response = "Socket is not initialized"; 
        } 
    
        return response; 
        } 
    
        public String UDPReceive(int portNumber, bool isBroadcast) 
        { 
        SocketAsyncEventArgs socketEventArg; 
    
        System.Diagnostics.Debug.WriteLine("calling Send(\"server\", portNumber, \" \", isBroadcast, out socketEventArg)"); 
        Send("servern", portNumber, " ", !isBroadcast, out socketEventArg); 
        Thread.Sleep(1000); 
    
        while (!isHasSent) 
        { 
         Thread.Sleep(1); 
        } 
        System.Diagnostics.Debug.WriteLine("calling Receive(portNumber, isBroadcast, socketEventArg)"); 
        return Receive(portNumber, isBroadcast, out socketEventArg); 
        } 
    
        /// <summary> 
        /// Receive data from the server 
        /// </summary> 
        /// <param name="portNumber">The port on which to receive data</param> 
        /// <returns>The data received from the server</returns> 
        public string Receive(int portNumber, bool isBroadcast, out SocketAsyncEventArgs socketEventArg) 
        { 
        string response = "Operation Timeout"; 
    
        // We are receiving over an established socket connection 
        if (_socket != null) 
        { 
         // Create SocketAsyncEventArgs context object 
         socketEventArg = new SocketAsyncEventArgs(); 
    
         System.Diagnostics.Debug.WriteLine("Receive(): setting remoteEndPoint"); 
         if (isBroadcast) 
         socketEventArg.RemoteEndPoint = new IPEndPoint(IPAddress.Broadcast, portNumber); 
         else 
         socketEventArg.RemoteEndPoint = new IPEndPoint(IPAddress.Any, portNumber); 
         System.Diagnostics.Debug.WriteLine("Receive(): remoteEndPoint correctly set"); 
    
         // Setup the buffer to receive the data 
         socketEventArg.SetBuffer(new Byte[MAX_BUFFER_SIZE], 0, MAX_BUFFER_SIZE); 
         System.Diagnostics.Debug.WriteLine("Receive(): SetBuffer() correctly called"); 
    
         // Inline event handler for the Completed event. 
         // Note: This even handler was implemented inline in order to make this method self-contained. 
         socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e) 
         { 
         if (e.SocketError == SocketError.Success) 
         { 
          System.Diagnostics.Debug.WriteLine("Receive(): SocketError.Success"); 
          // Retrieve the data from the buffer 
          response = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred); 
          response = response.Trim('\0'); 
         } 
         else 
         { 
          System.Diagnostics.Debug.WriteLine("Receive(): SocketError.Error"); 
          response = e.SocketError.ToString(); 
         } 
         System.Diagnostics.Debug.WriteLine("Receive(): Set()"); 
         _clientDone.Set(); 
         }); 
    
         System.Diagnostics.Debug.WriteLine("Receive(): Reset()"); 
         // Sets the state of the event to nonsignaled, causing threads to block 
         _clientDone.Reset(); 
    
         try 
         { 
         // Make an asynchronous Receive request over the socket 
         _socket.ReceiveFromAsync(socketEventArg); 
         } 
         catch (SocketException sockEx) 
         { 
         Console.WriteLine(sockEx.Message); 
         Console.WriteLine(sockEx.ErrorCode); 
         Console.WriteLine(sockEx.StackTrace); 
         Console.ReadLine(); 
         System.Diagnostics.Debug.WriteLine("errorCode=" + errorCode + " " + sockEx.Message + sockEx.ErrorCode + sockEx.StackTrace); 
         errorCode = 11; 
         response += "errorCode=" + errorCode + " " + sockEx.Message + sockEx.ErrorCode + sockEx.StackTrace; 
         } 
         catch (Exception ex) 
         { 
         Console.WriteLine(ex.Message); 
         Console.WriteLine(ex.StackTrace); 
         Console.ReadLine(); 
         System.Diagnostics.Debug.WriteLine("errorCode="+errorCode+" "+ex.Message + ex.StackTrace); 
         errorCode = 22; 
         response += "errorCode="+errorCode+" "+ex.Message + ex.StackTrace; 
         } 
         // Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds. 
         // If no response comes back within this time then proceed 
         System.Diagnostics.Debug.WriteLine("Receive(): _clientDone.WaitOne(TIMEOUT_MILLISECONDS)"); 
         _clientDone.WaitOne(TIMEOUT_MILLISECONDS); 
        } 
        else 
        { 
         socketEventArg = null; 
         response = "Socket is not initialized"; 
        } 
        System.Diagnostics.Debug.WriteLine("Receive(): response = " + response); 
        return response; 
        } 
    
        /// <summary> 
        /// Closes the Socket connection and releases all associated resources 
        /// </summary> 
        public void Close() 
        { 
        if (_socket != null) 
        { 
         _socket.Close(); 
        } 
        } 
    } 
    } 
    
  • +0

    您是在設備上還是在仿真器上運行它? – Antimony 2012-10-28 07:11:56

    回答

    0

    端口4502在Silverlight中不需要的Windows Phone,但只爲瀏覽器Silverlight應用程序。我」檢查你的代碼,因爲我有同樣的問題。