55

OK、これは私が数日間理解しようとしてきたものです。Windows Phone 7 には、電話機がマルチキャスト グループに参加し、グループとメッセージを送受信して互いに通信するアプリケーションがあります。注 - これは電話から電話への通信です。

Visual Studio 2012 の「Convert to Phone 8」機能を使用して、このアプリケーションを Windows Phone 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)

これらはすべて最新の OS を実行しており、開発者モードになっています。開発環境は、Visual Studio 2012 Professional を実行する Windows 8 Enterprise です。

仕事用のワイヤレス ネットワークについては詳しく説明できませんが、Phone 7 デバイス以外には問題はありません。

私が使用したホーム ワイヤレス ネットワークに関しては、これは基本的な BT ブロードバンド ルーターであり、「すぐに使える」設定は何も変更されていません。

明らかに 2 つのネットワークの構成方法に問題がありますが、Windows Phone 8 が UDP メッセージを実装する方法にも非常に明確な問題があります。

これは今私を怒らせているので、どんな意見でもいただければ幸いです。

4

3 に答える 3

1

別のマルチキャスト グループに参加しようとしたことがありますか? 224.0.1.1 は IANA 割り当ての時点で使用されているようです。ここですべてを見つけることができます。

おそらく、Windows Phone 8 では、着信メッセージをリッスンするように厳密にバインドされたサービス (カーネル モードで実行されているネットワーク サービスなど) があり、メッセージが転送されることはありません。

于 2013-09-13T13:32:43.800 に答える
1

ループバックを使用していることに気付きました。クライアントからメッセージを送信すると、送信したメッセージも受信されるという意味だと思います。これは、受信ハンドラーが起動することを意味します。一見非スレッドセーフな方法で受信バッファをクリアする効果があります。受信メソッドにいくつかの try catch を入れてみて、何か問題が発生していないかどうかを確認してください。ただし、代わりに、いずれにしても共有受信バッファーを使用しないこともできます。

于 2013-08-20T08:35:53.750 に答える