簡體   English   中英

Windows Phone 8上的UDP多播組

[英]UDP multicast group on Windows Phone 8

好的,這是我一直試圖弄清楚幾天的。 我們在Windows Phone 7上有一個應用程序,其中電話加入多播組,然后向該組發送和接收消息以相互通信。 注意 - 這是電話到電話的通信。

現在,我正在嘗試將此應用程序移植到Windows Phone 8 - 使用Visual Studio 2012中的“轉換為電話8”功能 - 到目前為止一切順利。 直到我嘗試測試手機到手機通訊。 手機似乎很好地加入了這個組,他們發送的數據報很好。 他們甚至收到他們發送給群組的消息 - 但是,沒有手機從其他手機收到消息。

以下是我的頁面背后的示例代碼:

// Constructor
public MainPage()
{
    InitializeComponent();
}

// The address of the multicast group to join.
// Must be in the range from 224.0.0.0 to 239.255.255.255
private const string GROUP_ADDRESS = "224.0.1.1";

// The port over which to communicate to the multicast group
private const int GROUP_PORT = 55562;

// A client receiver for multicast traffic from any source
UdpAnySourceMulticastClient _client = null;

// Buffer for incoming data
private byte[] _receiveBuffer;

// Maximum size of a message in this communication
private const int MAX_MESSAGE_SIZE = 512;

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    _client = new UdpAnySourceMulticastClient(IPAddress.Parse(GROUP_ADDRESS), GROUP_PORT);
    _receiveBuffer = new byte[MAX_MESSAGE_SIZE];

    _client.BeginJoinGroup(
        result =>
        {
            _client.EndJoinGroup(result);
            _client.MulticastLoopback = true;
            Receive();
        }, null);
}

private void SendRequest(string s)
{
    if (string.IsNullOrWhiteSpace(s)) return;

    byte[] requestData = Encoding.UTF8.GetBytes(s);

    _client.BeginSendToGroup(requestData, 0, requestData.Length,
        result =>
        {
            _client.EndSendToGroup(result);
            Receive();
        }, null);
}

private void Receive()
{
    Array.Clear(_receiveBuffer, 0, _receiveBuffer.Length);
    _client.BeginReceiveFromGroup(_receiveBuffer, 0, _receiveBuffer.Length,
        result =>
        {
            IPEndPoint source;

            _client.EndReceiveFromGroup(result, out source);

            string dataReceived = Encoding.UTF8.GetString(_receiveBuffer, 0, _receiveBuffer.Length);

            string message = String.Format("[{0}]: {1}", source.Address.ToString(), dataReceived);
            Log(message, false);

            Receive();
        }, null);
}

private void Log(string message, bool isOutgoing)
{
    if (string.IsNullOrWhiteSpace(message.Trim('\0')))
    {
        return;
    }

    // Always make sure to do this on the UI thread.
    Deployment.Current.Dispatcher.BeginInvoke(
    () =>
    {
        string direction = (isOutgoing) ? ">> " : "<< ";
        string timestamp = DateTime.Now.ToString("HH:mm:ss");
        message = timestamp + direction + message;
        lbLog.Items.Add(message);

        // Make sure that the item we added is visible to the user.
        lbLog.ScrollIntoView(message);
    });

}

private void btnSend_Click(object sender, RoutedEventArgs e)
{
    // Don't send empty messages.
    if (!String.IsNullOrWhiteSpace(txtInput.Text))
    {
        //Send(txtInput.Text);
        SendRequest(txtInput.Text);
    }
}

private void btnStart_Click(object sender, RoutedEventArgs e)
{
    SendRequest("start now");
}

為了簡單地測試UDP堆棧,我從這里找到的MSDN下載了樣本,並在一對Windows Phone 7設備上測試了它,它按預期工作。 然后我轉換到Windows Phone 8並部署到我的手機,設備似乎再次發起連接,用戶可以輸入他們的名字。 但是,設備再次無法查看或與其他設備通信。

最后,我使用新的DatagramSocket實現實現了一個簡單的通信測試,我再次看到成功啟動,但沒有設備間通信。

這與使用數據報套接字實現的頁面后面的代碼相同:

// Constructor
public MainPage()
{
    InitializeComponent();
}

// The address of the multicast group to join.
// Must be in the range from 224.0.0.0 to 239.255.255.255
private const string GROUP_ADDRESS = "224.0.1.1";

// The port over which to communicate to the multicast group
private const int GROUP_PORT = 55562;

private DatagramSocket socket = null;

private void Log(string message, bool isOutgoing)
{
    if (string.IsNullOrWhiteSpace(message.Trim('\0')))
        return;

    // Always make sure to do this on the UI thread.
    Deployment.Current.Dispatcher.BeginInvoke(
    () =>
    {
        string direction = (isOutgoing) ? ">> " : "<< ";
        string timestamp = DateTime.Now.ToString("HH:mm:ss");
        message = timestamp + direction + message;
        lbLog.Items.Add(message);

        // Make sure that the item we added is visible to the user.
        lbLog.ScrollIntoView(message);
    });
}

private void btnSend_Click(object sender, RoutedEventArgs e)
{
    // Don't send empty messages.
    if (!String.IsNullOrWhiteSpace(txtInput.Text))
    {
        //Send(txtInput.Text);
        SendSocketRequest(txtInput.Text);
    }
}

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
    socket = new DatagramSocket();
    socket.MessageReceived += socket_MessageReceived;

    try
    {
        // Connect to the server (in our case the listener we created in previous step).
        await socket.BindServiceNameAsync(GROUP_PORT.ToString());
        socket.JoinMulticastGroup(new Windows.Networking.HostName(GROUP_ADDRESS));
        System.Diagnostics.Debug.WriteLine(socket.ToString());
    }
    catch (Exception exception)
    {
        throw;
    }
}

private async void SendSocketRequest(string message)
{
    // Create a DataWriter if we did not create one yet. Otherwise use one that is already cached.
    //DataWriter writer;
    var stream = await socket.GetOutputStreamAsync(new Windows.Networking.HostName(GROUP_ADDRESS), GROUP_PORT.ToString());
    //writer = new DataWriter(socket.OutputStream);
    DataWriter writer = new DataWriter(stream);

    // Write first the length of the string as UINT32 value followed up by the string. Writing data to the writer will just store data in memory.
   // stream.WriteAsync(
    writer.WriteString(message);

    // Write the locally buffered data to the network.
    try
    {
        await writer.StoreAsync();
        Log(message, true);
        System.Diagnostics.Debug.WriteLine(socket.ToString());
    }
    catch (Exception exception)
    {
        throw;
    }
    finally
    {
        writer.Dispose();
    }
}

void socket_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
    try
    {
        uint stringLength = args.GetDataReader().UnconsumedBufferLength;
        string msg = args.GetDataReader().ReadString(stringLength);

        Log(msg, false);
    }
    catch (Exception exception)
    {
        throw;
    }
}

昨晚我帶着手機回家在我的家庭無線網絡上進行測試,很低,看到我得到了成功的設備通信。

所以回顧一下 - 我的遺留Windows Phone 7代碼在我的工作網絡上運行良好。 Windows Phone 8的端口(無實際代碼更改)不會發送設備間通信。 此代碼適用於我的家庭網絡。 代碼在附加調試器的情況下運行,並且在執行期間沒有任何錯誤或異常的跡象。

我正在使用的手機是:

Windows Phone 7 - Nokia Lumia 900(* 2),Nokia Lumia 800(* 3)Windows Phone 8 - Nokia Lumia 920(* 1),Nokia Limia 820(* 2)

這些都運行最新的操作系統,並處於開發人員模式。 開發環境是運行Visual Studio 2012 Professional的Windows 8 Enterprise

我無法告訴你很多關於無線網絡的工作 - 除了Phone 7設備沒有問題。

至於我使用的家庭無線網絡,這只是一個基本的BT寬帶路由器,沒有改變“開箱即用”的設置。

顯然,配置兩個網絡的方式存在問題,但Windows Phone 8實現UDP消息的方式也存在很明顯的問題。

任何輸入都會受到贊賞,因為這讓我很生氣。

我注意到你使用環回。 我認為這意味着當您從客戶端發送消息時,您也會收到您發送的消息。 這意味着您的接收處理程序將觸發。 它具有以看似無形的方式清除接收緩沖區的效果。 嘗試在你的接收方法中加入一些try catch,看看是否發生了任何不幸事件,但你可能只是在任何情況下都不使用共享接收緩沖區。

你有沒有試過加入另一個組播組? 因為在IANA分配中似乎正在使用224.0.1.1。 你找到了所有這里

也許在Windows Phone 8上,某些服務更嚴格地監聽進入的消息(例如,以內核模式運行的網絡服務)並且它們永遠不會轉發給您。

根據我的經驗,UDP多播在windows phone 7下工作非常奇怪,所以你應該為windows phone 8查看相同內容。

這是我的經歷:

  1. 檢查官方支持的內容,例如在Windows Phone OS 7.1(我在切換之前嘗試過的最后一個操作系統),支持TCP單播,UDP單播和UDP多播客戶端。
  2. 某些版本的Windows手機只有在客戶端首次打開它並且在不超過10秒內收到會話時才允許接收UDP會話,這似乎是Windows Phone上的某種安全問題。
  3. 嘗試使用不同的地址:224.0.0.0到224.0.0.255范圍內的多播地址是“眾所周知的”保留多播地址。
  4. 檢查虛擬機和真實電話設備中的行為可能會有所不同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM